Algorithm 手动移除O(n)中的重复项
我需要删除列表中的所有重复项,但前提是列表a中的项与列表b中的项相同。这是我当前的代码,但在10万个项目上,这需要花费数天的时间,有没有一种快速的方法可以做到这一点 谢谢你的帮助Algorithm 手动移除O(n)中的重复项,algorithm,Algorithm,我需要删除列表中的所有重复项,但前提是列表a中的项与列表b中的项相同。这是我当前的代码,但在10万个项目上,这需要花费数天的时间,有没有一种快速的方法可以做到这一点 谢谢你的帮助 List<int> ind = new List<int>(); List<int> used = new List<int>(); for (int i = 0; i < a.Count; i++)
List<int> ind = new List<int>();
List<int> used = new List<int>();
for (int i = 0; i < a.Count; i++)
{
for (int j = 0; j < a.Count; j++)
{
if (i != j&&!used.Contains(i))
{
if (a[j] == a[i] && b[i] == b[j])
{
ind.Add(j);
used.Add(j);
}
}
}
}
List<string> s2 = new List<string>();
List<string> a2 = new List<string>();
for (int i = 0; i < a.Count; i++)
{
if (!ind.Contains(i))
{
s2.Add(a[i]);
a2.Add(b[i]);
}
}
List ind=new List();
使用的列表=新列表();
for(int i=0;i
许多此类问题的关键在于正确的数据结构。为了避免重复,您需要使用集合,因为它们会自动删除重复项
下面是Java中的代码,我希望它与C中的代码类似:
import java.util.ArrayList;
导入java.util.HashSet;
导入java.util.List;
导入java.util.Random;
导入java.util.Set;
类副本
{
静态列表list1=新的ArrayList();
静态列表list2=新的ArrayList();
静态最终整型尺寸=100_000;
静态最终int最大值=1000_000;
公共静态void main(字符串[]args)
{
//用随机值填充列表以进行测试
随机r=新随机();
对于(int i=0;i这是一个需要考虑的一般算法。我们可以从升序排序这两个列表开始。使用一个好的排序算法,如归并排序,这将采用<代码> O(nLGN)。
time,其中N
是列表的长度。一旦我们支付了此罚金,我们只需要在每个列表中维护两个指针。一般算法基本上包括向上遍历两个列表,在第一个a
列表中搜索重复项,如果所讨论的值与b 列表。如果存在匹配项,则重复项将从a
列表中删除,否则我们将继续执行,直到到达a
列表的末尾。此过程仅为O(N)
,最大的惩罚是初始排序,即O(NlgN)
创建哈希集
首先,遍历列表b
,并将所有元素添加到HashSet中
然后,遍历列表a
中的每个元素。当您访问一个元素时,询问哈希集是否已经包含该元素。如果不包含,则它是一个新元素,因此只需保留它。如果包含,则它是一个重复元素,您可以将其从a
中删除
hashset可以执行O(1)中的是否有这个元素?
问题,因此对于整个列表,您有O(n)
有关更多信息,请查看。以“删除重复项”,我理解为“从n个相同的项中,保留第一个项并删除剩余的n-1”。如果是这样,则这是算法:
将列表b
转换为setb
。同时引入setA_dup
。运行列表A
,并针对每个项目:
- 如果在
A_dup
中找到项目,则将其从A
中删除
- 否则,如果在集合
B
中找到项目,则将其添加到A\u dup
- 重复一遍
检查集合中是否存在(包括A_dup
和B
)是O(1)操作,也就是在集合中添加新项。因此,您只需遍历列表A
,这总共给了我们O(n)。我想您要做的是找到不同的对,对吗
如果是这样,您可以在一行中使用Zip
和Distinct
以及一个C#Tuple(或使用匿名类型)来实现这一点
你的编程语言是什么?@TimBiegeleisen:在我看来,Java不正确。实际上,它看起来(可能)对我来说,C代码是正确的,但我想问清楚。语言不可知论者更好,但是的C#@TimBiegeleisen:哇,C和Java看起来非常相似!这只适用于在单个列表中使用重复项,我需要并排比较两个列表,我可能只是用一个我知道不在其中的字符连接这两个列表,放入哈希集,然后拆分它在C++中,你可以只做一个列表/一组对(a,b)@汉索尔森:也许我对ASK有不同的理解。我把他的问题解释为“从列表1中删除所有重复,但是只有当这个值也在列表2中时”。@KonradHöffner我也认为这是第一个,但原始代码和询问者的注释似乎表明这意味着“如果第二个列表中相同位置的值也是重复的”.我可能弄错了,这一切对meGood来说似乎都不清楚,但现在这个算法不仅会从列表a
中删除重复项,还会删除其中的所有元素(不是n-1
,而是n
)。op说:“我需要删除a
中的所有重复项,前提是a
中的项在列表b
中相同。”。一旦你有了一个散列,它将删除b
中的所有元素,你可以删除a
中的所有元素,这些元素也在b
中,但我不知道这将如何删除a
中的所有元素,因为如果一个元素在a
中而不在b
中,它将被保留。你不必反复浏览列表来查看add到HashSet
。签出HashSet(IEnumerable)
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
class Duplicates
{
static List<Integer> list1 = new ArrayList<>();
static List<Integer> list2 = new ArrayList<>();
static final int SIZE = 100_000;
static final int MAX_VALUE = 1000_000;
public static void main(String[] args)
{
// populate the lists with random values for testing
Random r = new Random();
for(int i=0; i<SIZE; i++)
{
list1.add(r.nextInt(MAX_VALUE));
list2.add(r.nextInt(MAX_VALUE));
}
Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);
// items that are in both lists
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
Set<Integer> notSeenYet = new HashSet<>(intersection);
List<Integer> list1Unique = new ArrayList<Integer>();
for(int n: list1)
{
if(intersection.contains(n)) // we may have to skip this one
{
if(notSeenYet.contains(n)) // no, don't skip, it's the first occurrence
{
notSeenYet.remove(n);
}
else
{
continue;
}
}
list1Unique.add(n);
}
System.out.println("list 1 contains "+list1Unique.size()+" values after removing all duplicates that are also in list 2");
}
}
var result = a.Zip(b, (x,y) => (x, y)).Distinct();
import java.util.*;
import java.util.stream.Collectors;
public class Test {
public static void main(String args[]) {
List<String> dupliKhaneList = new ArrayList<>();
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Zidan");
// Solution 1 if want to remove in list
List<String> uniqueList = dupliKhaneList.stream().distinct().collect(Collectors.toList());
System.out.println("DupliKhane => " + dupliKhaneList);
System.out.println("Unique 1 => " + uniqueList);
// Solution 2 if want to remove using 2 list
List<String> list1 = new ArrayList<>();
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Zidan");
List<String> list2 = new ArrayList<>();
list2.add("Zidan");
System.out.println("list1 => " + list1);
System.out.println("list2 => " + list2);
list1.removeAll(list2);
System.out.println("removeAll duplicate => " + list1);
}
}
DupliKhane => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
Unique 1 => [Vaquar, Khan, Zidan]
list1 => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
list2 => [Zidan]
removeAll duplicate => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar]