簡體   English   中英

在字符串的鏈表的鏈表中查找重復項的最有效方法-Java

[英]Most efficient way to find duplicates in a linkedlist of linkedlist of strings - java

讓我們假設我們有一個字符串鏈表的鏈表。

LinkedList<LinkedList<String>> lls = new LinkedList<LinkedList<String>> ();
LinkedList<String> list1 = new LinkedList<String>(Arrays.asList("dog", "cat", "snake"));
LinkedList<String> list2 = new LinkedList<String>(Arrays.asList("donkey", "fox", "dog"));
LinkedList<String> list3 = new LinkedList<String>(Arrays.asList("horse", "cat", "pig"));
lls.add(list1);
lls.add(list2);
lls.add(list3);

如您所見,這3個字符串鏈表是不同的,但也有一些共同點。 我的目標是編寫一個將每個列表與其他列表進行比較的函數,如果存在至少一個共同的元素(dog在list1和list2中),則返回TRUE,否則返回FALSE。

我認為我需要做的第一件事是比較列表之間所有可能的排列,列表之間的比較是逐元素進行的。 我不確定這是最有效的方法。 您能否提出一個最終最有效的想法?

假設不應該通過刪除元素或對元素進行排序來改變給定列表(順便說一下,它們具有O(nlogn)的復雜性),基本上,您需要一個函數作為實際解決方案的“構建塊”。 即,一種檢查一個集合是否包含另一個集合中包含的任何元素的函數。

當然,這可以通過在第二個集合上使用Collection#contains解決。 但是對於某些集合(尤其是列表),它具有O(n),而檢查的總運行時間為O(n * n)。

為避免這種情況,您可以創建一個包含第二個集合的所有元素的Set 對於Set ,保證contains方法為O(1)。

然后,可以使用Stream#anyMatch方便地進行實際檢查:

containing.stream().anyMatch(e -> set.contains(e))

因此,完整的示例可能是

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class DuplicatesInLinkedLists
{
    public static void main(String[] args)
    {
        LinkedList<LinkedList<String>> lls =
            new LinkedList<LinkedList<String>>();
        LinkedList<String> list1 =
            new LinkedList<String>(Arrays.asList("dog", "cat", "snake"));
        LinkedList<String> list2 =
            new LinkedList<String>(Arrays.asList("donkey", "fox", "dog"));
        LinkedList<String> list3 =
            new LinkedList<String>(Arrays.asList("horse", "cat", "pig"));
        lls.add(list1);
        lls.add(list2);
        lls.add(list3);

        checkDuplicates(lls);
    }

    private static void checkDuplicates(
        List<? extends Collection<?>> collections)
    {
        for (int i = 0; i < collections.size(); i++)
        {
            for (int j = i + 1; j < collections.size(); j++)
            {
                Collection<?> ci = collections.get(i);
                Collection<?> cj = collections.get(j);
                boolean b = containsAny(ci, cj);
                System.out.println(
                    "Collection " + ci + " contains any of " + cj + ": " + b);
            }
        }
    }

    private static boolean containsAny(Collection<?> containing,
        Collection<?> contained)
    {
        Set<Object> set = new LinkedHashSet<Object>(contained);
        return containing.stream().anyMatch(e -> set.contains(e));
    }
}

附帶說明:您發布的代碼在當前形式中幾乎毫無意義。 列表的聲明和創建通常應依賴List

List<List<String>> lists = new ArrayList<List<String>>();
lists.add(Arrays.asList("dog", "cat", "snake");
...

如果列表中的元素需要修改 ,那么您可以編寫

lists.add(new ArrayList<String>(Arrays.asList("dog", "cat", "snake"));

或者類似地,使用LinkedList而不是ArrayList ,但是對於草繪的用例,我無法想象為什么應該有一個強烈的理由完全故意使用LinkedList ……

將所有列表中的所有項目添加到一個列表中,然后對其進行排序( Collections.sort )。 然后遍歷它並檢查重復項。

例如

ArrayList<String> list = new ArrayList<>();
list.addAll(list1); // Add the others as well
Collections.Sort(list);
for (String s : list) {
    If (the item is the same as the previous item) {
        return true;
    }
}

使用retainAll()

    for (final LinkedList<String> ll : lls)
    {
        list1.retainAll(ll);
    }
    System.out.println("list1 = " + list1);

LinkedList不是檢測重復項的最佳集合。 如果可以,請嘗試使用HashSet,但是如果不能執行此操作,則仍可以將列表中的所有元素放入列表中。 哈希集包含沒有重復項的元素,因此,如果哈希表列表中存在重復元素,則哈希集將包含比所有列表更少的元素。

假設您要使用LinkedLists,並且不允許將其轉換為其他數據結構,那么您可以做的是創建一個接受可變數量的LinkedLists的方法。 從那里開始,您要獲取LinkedList的所有唯一組合,然后比較那些鏈接列表之間的所有唯一元素(如果找到一個公共元素),則將該鏈接列表對標記為公共。 您要如何跟蹤/返回數據(例如,一組具有共同元素的鏈表對)取決於您的輸出看起來像什么,但這就是我將使用的代碼的一般結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM