Algorithm 手动移除O(n)中的重复项

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++)

我需要删除列表中的所有重复项,但前提是列表a中的项与列表b中的项相同。这是我当前的代码,但在10万个项目上,这需要花费数天的时间,有没有一种快速的方法可以做到这一点

谢谢你的帮助

  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
转换为set
b
。同时引入set
A_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]