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