![](/img/trans.png)
[英]HQL (Hibernate) how to check if a list of elements is a subset of another list?
[英]How to check if a list is a subset of another list in java?
我正在尝试检查一个列表是否是 java 中另一个列表的子集。 我使用 for 循环来检查元素,并且我有一个名为 same 的变量,每次元素相同时都会增加该变量。 问题是只有当元素位于相同的位置时,列表才返回真
例如 :
(0,1) (0,1,2,3 ) true
(1,0) (0,1,2,3) false
我写了下面的代码:
public Boolean contains(ItemsList ilist) {
int same = 0;
if (empty()) {
return false;
} else {
ItemNode a = this.first;
ItemNode b = ilist.first;
for (b = ilist.first; b != null; b = b.next) {
for (a = this.first; a != null; a = a.next) {
if (a.item == b.item) {
same++;
}
}
}
}
return (same > 0);
}
解决此问题的方法与解决子字符串匹配问题非常相似。
首先检查是否应该是子集列表的第一个元素(此后称为SSL)。
一旦找到匹配项,请注意索引(此后在找到匹配项的主列表中将其称为myGuy ,请继续检查SSL的后续元素是否与主列表匹配。
如果您的比赛完成,则只需返回即可。 如果没有,那么您可以做两个之一。 如果主列表中还有元素,则递增myGuy ,然后它就成为您开始在主列表中进行迭代的新索引。
如果没有剩余元素并且仍然没有完全匹配,则它不是子集。
您可以在Java中执行以下操作:
private static boolean checkSubList(int[] mainList, int[] subList) {
int currentIteratingPointer;
int matchCounter = 0;
for (int i = 0; i < mainList.length; i++) {
currentIteratingPointer = i;
for (int j = 0; j < subList.length; j++) {
if (mainList[currentIteratingPointer] == subList[j]) {
System.out.println(mainList[currentIteratingPointer]);
++matchCounter;
++currentIteratingPointer;
} else {
--matchCounter;
break;
}
}
i = currentIteratingPointer;
}
return matchCounter == subList.length; // You can count the number of occurance of the sublist if you change
// it to int and return the matchCounter a
}
试试这个来源
public class ListTest {
List small = new ArrayList<>();
List big = new ArrayList<>();
public static void main(String args[]) {
ListTest g = new ListTest();
g.populateList();
boolean bFlag = g.checkIfSubset();
System.out.println("====is subset====>" + bFlag);
}
private boolean checkIfSubset() {
for (Object in : small) {
if (!big.contains(in)) {
return false;
}
}
return true;
}
private void populateList() {
small.add(11);
small.add(23);
big.add(11);
big.add(2);
big.add(23);
big.add(24);
}
}
问题是,对于Set而言, contains
将是很好的(对于唯一数字),但对于List
一个朴素的contains
需要两个嵌套循环,二次复杂度O(N²):两个包含100个元素的列表将需要10,000个步骤。 因此,应该将列表转换为集合,或者对列表进行排序 。
列表排序可以是O(N log N),但是对于您似乎拥有的链表,它保持不变:
public ItemsList sort(ItemsList list) {
ItemsList sortedList = new ItemsList();
for (ItemNode node : list) {
sortedList.insertSorted(node.item);
}
return sortedList;
}
但是排序后,您可以按照线性复杂度O(N)进行操作。
public boolean contains(ItemsList ilist) {
ItemsList sortedThis = this.sorted();
ItemsList sortedOther = iList.sorted();
ItemNode node = sortedThis.first;
ItemNode other = otherList.first;
while (node != null) {
if (other == null) {
break; // return true;
}
if (other.item < node.item) {
break; // return false;
}
if (other.item == node.item) {
other = other.next; // Match found.
}
node = node.next;
}
return other == null;
}
由于列表可以包含重复项,因此请进行排序。
因此,基本上,您想将一个列表的字谜找到另一个列表。
这是我的字符串字谜的实现
abcde,dbc-> true
签出我的代码,并尝试在您的用例中实现它。
public boolean findStringAnagrams(String str, String pattern) {
Map<Character, Integer> charMap = new HashMap<>();
for (int i = 0; i < pattern.length(); i++) {
charMap.put(pattern.charAt(i), charMap.getOrDefault(pattern.charAt(i), 0) + 1);
}
Integer windowStart = pattern.length() - 1;
for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
Character c = str.charAt(windowEnd);
charMap.computeIfPresent(c, (key, val) -> val - 1);
if (charMap.containsKey(c) && charMap.get(c) == 0)
charMap.remove(c);
if (windowStart < windowEnd) {
if (charMap.size() == 0) {
return true;
}
charMap.put(str.charAt(windowStart), charMap.getOrDefault(str.charAt(windowStart), 0) + 1);
windowStart++;
}
}
return false;
}
请注意,似乎Collections.indexOfSubList
可能不适用于 Strings ? 这种方法有效,使用 Apache Commons 集合
import org.apache.commons.collections.CollectionUtils;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
private static boolean isSublistOfList(List list, List sublist) {
List dedupedSublist = (List) sublist.stream().distinct().collect(Collectors.toList());
boolean result = CollectionUtils.isSubCollection(dedupedSublist, list);
return result;
}
@Test
void testIt(){
List<String> parentDataList = List.of("this", "is", "a", "test", "string", "and", "a", "test", "other");
List<String> child1 = List.of("a", "test");
List<String> child2 = List.of("this", "string");
List<String> child3 = List.of("is", "not", "test");
List<String> child4 = List.of("string", "this", "this");
assertEquals(true, isSublistOfList(parentDataList, child1));
assertEquals(true, isSublistOfList(parentDataList, child2));
assertEquals(false, isSublistOfList(parentDataList, child3));
assertEquals(true, isSublistOfList(parentDataList, child4));
List<Integer> parentList1 = List.of(1,2,3,4,5);
List<Integer> subList1 = List.of(4);
List<Integer> subList2 = List.of(5,4,3,2,2,1);
List<Integer> subList3 = List.of(5,6);
List<Integer> subList4 = List.of();
assertEquals(true, isSublistOfList(parentList1, subList1));
assertEquals(true, isSublistOfList(parentList1, subList2));
assertEquals(false, isSublistOfList(parentList1, subList3));
assertEquals(true, isSublistOfList(parentList1, subList4));
}
def isSubset(l,s):
if len(s) > len(l):
return False
elif s == l:
return True
elif len(s) <= 0:
return True
else:
for i in range(len(l)):
if l[i] == s[0]:
n = 1
while n < len(s) and l[i+n] == s[n]:
n += 1
if n == len(s):
return True
只需对要检查的列表的每个循环执行一次,即可检查该列表的元素是否包含在较大的列表中。 像这样
var bigList = [0,1,2,3,4,5]
var smallList = [1,2]
checkIfSubset(bigList, smallList)
bool checkIfSubset(list bigList, list smallList){
var isSubset = false
foreach(element in smallList){
if(bigList.contains(element){
isSubset = true
}
else{
isSubset = false
break
}
}
return isSubset
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.