如何检查一个列表是否是 java 中另一个列表的子集?
How to check if a list is a subset of another list in java?
我正在尝试检查一个列表是否是 java 中另一个列表的子集。我使用 for 循环来检查元素,并且我有一个名为 same 的变量,每次元素相同时该变量都会递增。问题是列表 returns 仅当元素处于相同位置
时才为真
例如:
(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 匹配主列表。
如果你的比赛已经完成,那么只需 return。如果没有,那么您可以执行两者之一。如果主列表有剩余元素,则递增 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);
}
}
问题是 contains
对于 Set 会很好(对于唯一数字),但是对于 List
一个天真的 contains
需要两个嵌套循环,二次复杂度 O(N²) :两个包含 100 个元素的列表需要 10,000 个步骤。因此,应该将列表转换为集合,或者 sort 列表。
列表排序可能是 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 -> 真
检查我的代码并尝试在您的用例中实现它。
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
可能不适用于字符串?这种方法有效,使用 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
尝试:
list1.containsAll(list2);
如果 list2 是 list1 的子集,这将 return 一个 'True',否则 return 'False'
我正在尝试检查一个列表是否是 java 中另一个列表的子集。我使用 for 循环来检查元素,并且我有一个名为 same 的变量,每次元素相同时该变量都会递增。问题是列表 returns 仅当元素处于相同位置
时才为真例如:
(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 匹配主列表。
如果你的比赛已经完成,那么只需 return。如果没有,那么您可以执行两者之一。如果主列表有剩余元素,则递增 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);
}
}
问题是 contains
对于 Set 会很好(对于唯一数字),但是对于 List
一个天真的 contains
需要两个嵌套循环,二次复杂度 O(N²) :两个包含 100 个元素的列表需要 10,000 个步骤。因此,应该将列表转换为集合,或者 sort 列表。
列表排序可能是 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 -> 真
检查我的代码并尝试在您的用例中实现它。
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
可能不适用于字符串?这种方法有效,使用 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
尝试:
list1.containsAll(list2);
如果 list2 是 list1 的子集,这将 return 一个 'True',否则 return 'False'