在具有整数的数组中,一个值在数组中两次.你怎么决定哪一个?

max*_*yne 10 c arrays xor

假设数组的整数在1到1,000,000之间.

我知道解决这个问题的一些流行方法:

  1. 如果包含1到1,000,000之间的所有数字,找到数组元素的总和并从总和中减去它(n*n + 1/2)
  2. 使用哈希映射(需要额外的内存)
  3. 使用位图(减少内存开销)

我最近遇到了另一个解决方案,我需要一些帮助来理解它背后的逻辑:

保留一个基数累加器.您使用索引和该索引处的值进行异或或累加器.

x ^ C ^ x == C这个事实在这里是有用的,因为每个数字将被xor'd两次,除了那里的两次,这将出现3次.(x ^ x ^ x == x)最终索引,将出现一次.因此,如果我们使用最终索引对累加器进行种子处理,则累加器的最终值将是列表中的数字两次.

如果有人能够帮助我理解这种方法背后的逻辑,我会很感激(用一个小例子!).

Jon*_*Jon 8

假设你有一个累加器

int accumulator = 0;
Run Code Online (Sandbox Code Playgroud)

在循环的每个步骤中,使用i和XOR累加器v,其中i是循环迭代的索引,并且vi数组的第th个位置的值.

accumulator ^= (i ^ v)
Run Code Online (Sandbox Code Playgroud)

通常,i并且v将是相同的数字,所以你最终会做

accumulator ^= (i ^ i)
Run Code Online (Sandbox Code Playgroud)

但是i ^ i == 0,这将最终成为一个无操作,累加器的价值将保持不变.此时我应该说数组中数字的顺序无关紧要,因为XOR是可交换的,所以即使数组被混洗开始,结尾处的结果仍然应该是0(累加器的初始值).

现在如果一个数字在数组中出现两次怎么办?显然,这个数字在XORing中会出现三次(一个用于索引等于数字,一个用于数字的正常外观,一个用于额外外观).此外,其他一个数字只会出现一次(仅适用于其索引).

此解决方案现在假设仅出现一次的数字等于数组的最后一个索引,或者换句话说:数组中的数字范围是连续的并且从要处理的第一个索引开始(编辑:感谢caf提出这个单挑评论,这就是我真正想到的,但是在撰写时我完全搞砸了).有了这个(N只出现一次)作为给定,考虑从开始

int accumulator = N;
Run Code Online (Sandbox Code Playgroud)

N在XORing中有效地再次出现两次.在这一点上,我们留下的数字只出现两次,只有一次出现三次.由于两次出现的数字将XOR输出为0,因此累加器的最终值将等于出现三次的数字(即一次额外).