Algorithm 什么';在一组一百万个数字中找到一个唯一的数字是一种有效的算法吗?

Algorithm 什么';在一组一百万个数字中找到一个唯一的数字是一种有效的算法吗?,algorithm,data-structures,Algorithm,Data Structures,我在一次采访中被问到这个问题。在一百万个数字中,除一个数字外,所有数字都有一个副本。如何找到那个号码?我应该使用哪种算法来获得良好的时间和空间复杂度?我有了一个使用EXOR gate的想法,但我在部署方面仍然落后。按顺序用于所有数字 对于以下编号列表: 1,2,3,4,3,2,1 让^表示独占析取(或xor) 然后, 1^2^3^4^3^2^1=4试试这个 int[] a = {1, 2, 1, 2, 3}; Arrays.sort(a); for(int i = 0;

我在一次采访中被问到这个问题。在一百万个数字中,除一个数字外,所有数字都有一个副本。如何找到那个号码?我应该使用哪种算法来获得良好的时间和空间复杂度?我有了一个使用EXOR gate的想法,但我在部署方面仍然落后。

按顺序用于所有数字

对于以下编号列表:

1,2,3,4,3,2,1

^
表示独占析取(或
xor

然后,
1^2^3^4^3^2^1=4

试试这个

    int[] a = {1, 2, 1, 2, 3};
    Arrays.sort(a);
    for(int i = 0; i < a.length; i++) {
        if (i == 0 && a[i] != a[i + 1] || i == a.length -1 || a[i] != a[i - 1] && a[i] != a[i + 1]) {
            System.out.println(a[i]);
            break;
        }
    }
int[]a={1,2,1,2,3};
数组。排序(a);
for(int i=0;i
以下可能会解决您的问题:

复杂性:
O(N)

或 复杂性:
O(N日志N)

int find_unique(std::vector&v)
{
if(v.empty()){throw std::runtime_error(“空向量”);}
如果(v.size()==1){返回v[0];}
排序(v.begin(),v.end());
如果(v[0]!=v[1]){返回v[0];}
对于(inti=1,size=v.size();i+1
另一个简单的解决方案:可以使用两个位集,一个用于标记数字的存在,另一个用于标记重复。我们遍历数组并标记每个元素的存在和重复。然后,我们遍历位集,找到一个标记为存在但未标记为重复的数字

int[] numbers = new int[] { 1, 1, 2, 2, 3, 4, 4, 5, 5 };

    BitSet bs1 = new BitSet();
    BitSet bs2 = new BitSet();

    int largestNumber = 0;

    for (int i = 0; i < numbers.length; i++) {
        int number = numbers[i];
        if (bs1.get(number) == false) {
            // Mark for existence
            bs1.set(number);
        } else {
            // Mark for duplicating
            bs2.set(number);
        }

        if (number > largestNumber) {
            largestNumber = number;
        }
    }

    for (int i = 0; i <= largestNumber; i++) {
        if (bs1.get(i) && !bs2.get(i)) {
            System.out.println("Non duplicating number is:  " + i);
        }
    }

}
int[]numbers=新的int[]{1,1,2,2,3,4,4,5};
位集bs1=新位集();
位集bs2=新位集();
int largestNumber=0;
for(int i=0;i最大编号){
最大数量=数量;
}
}

对于(inti=0;i我相信如果我们结合快速排序(搜索)技术和xor,我们可以得到尽可能快的代码。虽然我正在尝试,但如果这个想法是错误的,请纠正我

顺便说一句,这有很多用例。虽然这个问题与语言无关,并且需要清晰的算法,但我要提到一些读者可能会发现有用的用例

0可以是重复的…或负数

System.out.println(33^33^7^0^0^5^7^5);
给出了0(这里0是重复的)

重复项可能超过2个:

System.out.println(1^1^2^3^3);
给出的是1,而不是2


再者,这个问题可能比我们最初想象的要复杂。

对于大量的输入项(与只有几个数字的示例相反)将输入输入到某些数据结构中需要花费相当长的时间。我正在考虑将这一必要的时间作为计算过程的一部分,将其放入一个映射中。映射的值仅为一个数字的一个值。我假设数据是正确的,因此我省略检查,但如果有多个nu只出现一次的MBER将只返回第一次

应该有进一步优化的空间,例如,通过值访问地图,只需查找具有1的地图。我认为使用Boost.Bimap可以轻松实现这一点

int getSingleNumber(){

map<int, int> numbers;

for (all input items)
    {
    numbers[currentInputItem]++;
    }

for( map<int,int>::iterator ii=numbers.begin(); ii!=numbers.end(); ++ii)
{
    if ( (*ii).second == 1 ) return (*ii).first;
}
}
int getSingleNumber(){
地图编号;
用于(所有输入项)
{
数字[currentInputItem]++;
}
for(map::iterator ii=numbers.begin();ii!=numbers.end();++ii)
{
if(*ii).second==1)返回(*ii).first;
}
}

你走的路是正确的,你到底有什么问题?告诉我们到目前为止你都做了些什么?@Angew:“有重复项”并不意味着“正好有两个”,是吗?好吧,我猜从字面意义上来说…(但不是堆栈溢出的意思!-)@KerrekSB问题是“有重复项”更不用说XOR要工作,每个副本都必须有偶数。你知道这些数字吗?有符号/无符号,数据类型,它们是从开始排序的吗,它们都是以一个特定的N开头的整数吗?始终要记住另外一个问题:找到两个唯一的数字。这是昂贵的计算这将是昂贵的,几乎O(N)将是从数字到发生的哈希映射这将花费很多时间。。排序算法在列表O(nlogn)上,你有100万。。。也much@TarekSalah问题是百万。@TarekSalah百万并没有那么大,因为今天的计算机可以在毫秒内完成排序。我认为这是一个更好的解决方案,因为像X-OR-one一样,它并不假设重复项是均匀的。您应该添加一些解释,您的解决方案是正确的:)System.out.println(1^1^2^3^3^3);印刷品1@EvgeniyDorofeev:显然,
2^3
1
这只在每个值出现偶数的情况下才有效,但我认为重复在这里表示“两个”case@MadHatter但这应该是你增加记忆复杂性的原因。。。
int find_unique(std::vector<int>& v)
{
    if (v.empty()) { throw std::runtime_error("empty vector"); }
    if (v.size() == 1) { return v[0]; }
    std::sort(v.begin(), v.end());
    if (v[0] != v[1]) { return v[0]; }

    for (int i = 1, size = v.size(); i + 1 < size; ++i) {
        if (v[i] == v[i - 1]) { continue; }
        if (v[i] == v[i + 1]) { ++i; continue; } // we may skip v[i + 1]
        return v[i];
    }
    return v.back();
}
int[] numbers = new int[] { 1, 1, 2, 2, 3, 4, 4, 5, 5 };

    BitSet bs1 = new BitSet();
    BitSet bs2 = new BitSet();

    int largestNumber = 0;

    for (int i = 0; i < numbers.length; i++) {
        int number = numbers[i];
        if (bs1.get(number) == false) {
            // Mark for existence
            bs1.set(number);
        } else {
            // Mark for duplicating
            bs2.set(number);
        }

        if (number > largestNumber) {
            largestNumber = number;
        }
    }

    for (int i = 0; i <= largestNumber; i++) {
        if (bs1.get(i) && !bs2.get(i)) {
            System.out.println("Non duplicating number is:  " + i);
        }
    }

}
int getSingleNumber(){

map<int, int> numbers;

for (all input items)
    {
    numbers[currentInputItem]++;
    }

for( map<int,int>::iterator ii=numbers.begin(); ii!=numbers.end(); ++ii)
{
    if ( (*ii).second == 1 ) return (*ii).first;
}
}