How to check if a list is a subset of another list in java?

萝らか妹 提交于 2020-01-24 19:24:42

问题


I'm trying to check if a list is a subset of another in java . I used the for loop to check the elements and i have a variable called same that is incremented each time the elements are the same . The problem is that the list returns true only if the elements are in identical positions

For example :

(0,1) (0,1,2,3 ) true
(1,0) (0,1,2,3) false 

I have written the code below :

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);
}

回答1:


The approach to solve this problem is very similar to solving substring matching problem.

You start by checking if the first element of the supposedly subset list(henceforth to be refereed to as SSL).

Once you get a match, note the index (henceforth will be referred to as myGuy in the main list where the match is found, proceed to check if the subsequent elements of SSL matches the main list.

If your match is complete then simply return. If not, then you can do one of the two. If the main list has elements left, then increment myGuy and then it becomes the new index from where you start to iterate in the main list.
If no elements are left and still no complete match then it's not a subset.

Here is how you can do it in 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
}



回答2:


The problem is that contains for Set would be fine (for unique numbers), but for List a naive contains requires two nested loops, quadratic complexity O(N²): two lists of 100 elements would need 10,000 steps. Hence one should either convert the list(s) to sets, or sort the lists.

List sorting could be O(N log N), but for a linked list as you seem to have it stays the same:

public ItemsList sort(ItemsList list) {
    ItemsList sortedList = new ItemsList();
    for (ItemNode node : list) {
        sortedList.insertSorted(node.item);
    }
    return sortedList;
}

But after sorting you could do as you said, with a linear complexity 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;
}

As lists can contain duplicates, go with sorting.




回答3:


So basically you want to find anagrams of one list into another.

here is my implementation for string anagrams

abcde, dbc -> true

Checkout my code and try to implement it in your use case.

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;
    }



回答4:


Try this source

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);
    }

}


来源:https://stackoverflow.com/questions/59049534/how-to-check-if-a-list-is-a-subset-of-another-list-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!