使用xor解释在数组中找到两个非重复的整数

时间:2014-04-09 04:13:11

标签: c arrays algorithm

鉴于[1,1,4,5,5,6],我们可以将46视为非重复整数。

XOR使用#include <stdio.h> #include <stdlib.h> /* This finction sets the values of *x and *y to nonr-epeating elements in an array arr[] of size n*/ void get2NonRepeatingNos(int arr[], int n, int *x, int *y) { int xor = arr[0]; /* Will hold xor of all elements */ int set_bit_no; /* Will have only single set bit of xor */ int i; *x = 0; *y = 0; /* Get the xor of all elements */ for(i = 1; i < n; i++) xor ^= arr[i]; /* Get the rightmost set bit in set_bit_no */ set_bit_no = xor & ~(xor-1); /* Now divide elements in two sets by comparing rightmost set bit of xor with bit at same position in each element. */ for(i = 0; i < n; i++) { if(arr[i] & set_bit_no) *x = *x ^ arr[i]; /*XOR of first set */ else *y = *y ^ arr[i]; /*XOR of second set*/ } }

以下是作者提出的算法:

4^6

我对set_bit_no之后的内容感到困惑。我很困惑{{1}}如何运作(包括动机)以及之后的任何事情。

有人可以尝试以更简单的英语方式解释它吗?感谢。

4 个答案:

答案 0 :(得分:20)

如果我们有重复的数字对,它们不会向xor结果添加任何内容,因为它们的xor将为零。只有一对不同的数字会将非零位添加到xor结果中。

a xor a = 0
[a, b, c, b, d, a]
a xor b xor c xor b xor d xor a = c xor d

现在在c x或d中,唯一的设置位是c和d中不同的位。 我们说第3位是在c xor d中设置的。这意味着如果c中第3位为0,则d中为1,反之亦然。

因此,如果我们将所有数字分成2组,则包含所有数字的第3位为0,而其他第3位为1,则c和d肯定会转到不同的组。并且所有相同数字对将成为同一组。 (位3在a和0都是1)

让我们说这些小组是

[a c a] and [b d b]
xoring them
a xor c xor a = c (The first number)
b xor d xor b = d (The second number)

群体的其他可能性

[c] and [a b d b a]
xoring them
c = c (The first number)
a xor b xor d xor b xor a = d (The second number)

[a b c b a] and [d]
xoring them
a xor b xor c xor b xor a= c (The first number)
d = d (The second number)

关于

set_bit_no = xor & ~(xor-1);

如果输入数组由自然数组成,则xor为正数 xor&amp; ~xor为零(定义为所有位都被反转) 从xor减去1,

  1. 如果最右边的位为零,则将其设置为1并退出
  2. 将最右边的位重置为零并尝试将1添加到下一位(步骤1)
  3. 简而言之,1的所有最右边的位将变为零(倒退,类似于xor),第一个(最右边)的零位将变为1(与xor相同)。现在开始,这个新设置的1位的所有位在xor和〜(xor-1)中都是不同的,所以它们将生成0,所有新设置的1位都在xor和〜(xor- 1)因此它们将产生0.在两种情况下,只有位于〜(xor-1)中新设置1的位的位是1,因此在表达式xor&amp;中只设置该位。 〜(XOR-1)

答案 1 :(得分:2)

这里解释的简单方法是,当你执行a^b时,只设置那些在b中具有不同值的位位置。因此,如果您将数组中的元素与a^b中特定设置位的值进行分组,那么a和b将在不同的组中作为xor,组将取消其他组,两个组的结果将为a和b。< / p>

示例: -

a = 4 
b = 6 
a^b = 2

Set_bit_pos = 1

Arr = [1,1,4,5,5,6]

Grouping according to bit no 1 

x = [6] where bit1 is 1 

y = [4,1,1,5,5] where bit1 is 0

Xoring 

x = 6 

y = 4^1^1^5^5 = 4

答案 2 :(得分:2)

此算法仅在

时才有效
1) elements are non-zero
2) contains no more than 2 non-repeating integers. If only 1
   non-repeating, one of the result (x or y) will be 0.
3) the repeated numbers occurs in pairs (ie. 2,4,6....)

如果0是可能的数字,那么您就无法区分找到的答案或没有答案。

通过对所有元素进行异或运算,可以得出2个非重复整数之间的差异(即示例中为4 ^ 6)。这是因为所有其他元素都会重复(即偶数次),而在XOR中,它们会自行取消。重要的是要注意XOR是可交换的(即,顺序并不重要^ b = b ^ a)

现在是set_bit_no。这只是存储最右边的设置位或xor。为什么最合适?因为我猜很容易。但是任何一点都行。 xor变量中的设置位包含4到6之间不同的位。

100 ^ 110 = 010

第二位是1,因为4和6之间的唯一位不同。同样,3和8之间的差异

0011 ^ 1000 = 1011

表示第4位,第2位和第1位在3和8之间不同。

获取设置位并在if条件下使用它的原因是为了确保将答案(4和6)写入不同的变量(x或y)。为什么这样做?因为set bit保证2个答案在该位位置包含不同的值。

if(arr[i] & set_bit_no)

答案 3 :(得分:0)

当xor两个相等的值时,它们会取消。这允许揭示非重复对。

XOR(aabbccddeeffgh) = XOR(gh) = ...1...

了解gh不同的任何位允许在两个子集中设置gh

...0... => XOR(aabbcceeg) = g

...1... => XOR(ddffh) = h