繁体   English   中英

java - 如何检查一个列表是否是另一个列表的子集?

[英]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  

尝试:

list1.containsAll(list2);

如果 list2 是 list1 的子集,这将返回“真”,否则返回“假”

参考

只需对要检查的列表的每个循环执行一次,即可检查该列表的元素是否包含在较大的列表中。 像这样

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM