【问题标题】:Explain using xor to find two non-duplicate integers in an array解释使用 xor 在数组中查找两个不重复的整数
【发布时间】:2014-05-22 01:42:08
【问题描述】:

给定[1,1,4,5,5,6],我们可以找到46 是不重复的整数。

有一个solution 使用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*/
  }
}

我对@9​​87654328@ 之后的内容感到困惑。我很困惑set_bit_no 是如何工作的(包括动机)以及之后的任何事情。

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

【问题讨论】:

  • 如果在 xor 中设置的第一个位在位置 k,那么所有高于 k 的位在 xor 和 ~(xor-1) 中都会不同,导致零位和所有位在更低的位置比 k 在 xor 和 ~(xor - 1) 中都为零,结果为零。只有位置 k 的位会在两者中设置,从而导致 set_bit_no 的值正确。有关更多详细信息,请查看我的答案。
  • 您应该已经解释了数字是成对出现的,但其中两个是成对出现的。
  • 重复this

标签: c arrays algorithm


【解决方案1】:

如果我们重复了一对数字,它们不会对 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 xor d 中,唯一设置的位是 c 和 d 中不同的位。 假设在 c xor d 中设置了第 3 位。这意味着如果位 3 在 c 中为 0,则在 d 中为 1,反之亦然。

因此,如果我们将所有数字分成 2 组,其中一个包含所有第 3 位的数字为 0,而另一个包含第 3 位为 1 的数字,c 和 d 肯定会分到不同的组。并且所有相同的数字对将进入同一组。 (第 3 位要么在 a 上为 1,要么在 a 上均为 0)

假设组是

[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 & ~xor 为零(定义为所有位反转) 在 xor 中减去 1,

  1. 如果最右边的位为零,它将被设置为 1 并退出
  2. 将最右边的位重置为零并尝试将 1 加到下一位(步骤 1)

简而言之,所有为 1 的最右边的位将变为零(类似于 xor 反转),第一个(最右边的)零位将变为 1(与 xor 相同)。现在在 anding 上,这个新设置的 1 位左边的所有位在 xor 和 ~(xor-1) 中都不同,所以它们会生成 0,这个新设置的 1 位右边的所有位在 xor 和 ~(xor- 1) 所以它们会生成 0。只有在 ~(xor-1) 中新设置为 1 的位在这两种情况下都是 1,所以只有这个位会在表达式 xor & ~(xor-1) 中设置

【讨论】:

  • 喜欢这个set_bit_no = xor &amp; ~(xor-1);
  • 我想更正一件事。从 xor 中减去 1 将使最右边的所有零位为 1,第一个非零位为 0,其余部分保持不变。
【解决方案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 是可交换的(即顺序无关紧要 a^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)

【讨论】:

  • 是的,它适用于自然数,但如果满足前提条件 2(不超过或少于 2 个重复数字),它同样适用于零。如果存在一对零,则算法将忽略它。如果有一个零,它会在这个算法中正确计算。
  • 就像我说的,如果 0 可以是数组中的一个元素,那么数组必须包含 2 个不重复的整数。否则,如果它只包含 1 个非重复数字,算法将返回 x 或 y 作为 0,您无法判断该 0 是因为数组中有一个 0 还是只有 1 个非零非重复数字数组。想象一个数组 [0,0,1]。算法会返回 0 和 1。所以这是错误的。
  • 如果您怀疑输入中是否严格遵循前提条件 2,您可以通过计算零的出现次数来轻松处理这种情况。
  • @MohitJain 不是我怀疑 :-)。但是需要明确定义函数的输出是什么意思。 IE。当函数返回 x=1 时,y=0。这是什么意思? x=1 是微不足道的。现在 y=0 并不是那么简单。这是否意味着“没有答案”或“0 不重复”?现在您建议遍历整个数组并计算零的数量。这是可能的,但作为该函数的用户,我希望该函数能够返回正确且清晰的结果。
  • @MohitJain 我猜该函数的先决条件类似于“数组必须恰好包含 2 个非重复整数”。然后返回 0 显然意味着数组中肯定有 1 个零。
【解决方案3】:

这里解释的简单方法是,当您执行a^b 时,只会设置那些在 a 和 b 中具有不同值的位位置。因此,如果您将数组中的元素与它们在a^b 中特定设置位的值进行分组,那么 a 和 b 将在不同的组中,因为 xor-ing 该组将抵消其他组,并且两组的结果将是 a 和 b。

示例:-

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、3、4 或其他位置?我们如何确定使用的正确位置?
  • @user423455 对不起,我的错误 5 应该与 4 分组,因为它是 b101 所以 bit1 是 0 而不是 1。不需要取最右边的设置位,但任何设置位都可以,因为那时 x & y 将被分成不同的组并将它们分开
【解决方案4】:

当您对两个相等的值进行异或运算时,它们会抵消。这允许显示非重复对。

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

知道gh 不同的任何位允许将gh 放在两个子集中:

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

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

【讨论】:

    猜你喜欢
    • 2011-12-22
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2013-06-27
    • 2018-07-28
    • 1970-01-01
    • 2015-08-23
    相关资源
    最近更新 更多