按位XOR运算符查找缺少的唯一ID

时间:2016-12-16 09:23:22

标签: java bitwise-operators

我有一个正整数的数组。除了此数组中的一个元素之外的所有元素都没有重复。找到唯一元素的方法是使用XOR按位运算符,仅当元素之一为1时返回1,否则返回false。

以下是代码:

public class Bitter {

    public static void main(String[] args) {
        int[] deliveryIds = {34, 40, 2, 21, 50, 40, 34, 2, 50};
        System.out.println(new Bitter().findUniqueDeliveryId(deliveryIds));
    }

    public int findUniqueDeliveryId(int[] deliveryIds) {
        int uniqueDeliveryId = 0;

        for(int i = 0; i < deliveryIds.length; i++) {
            uniqueDeliveryId ^= deliveryIds[i];
        }

        return uniqueDeliveryId;
    }

}

在循环中,数组中的每个整数都与从1开始的uniqueId进行异或。然后,0与34进行异或。结果然后与数组40中的下一个整数进行异或运算通过整个阵列。

即使在设置断点并一次遍历整个流程之后,我仍然无法理解,如何使用uniqueId(从它的值0开始)进行异或可以帮助我们找到数组中的非重复整数?

不应该像自己的40个XOR一样(导致值为0),以确认它是重复的。与此不同的是,我们与数组中的第一个整数进行异或运算,结果与数组中的后续数字相对应。我缺少什么/

2 个答案:

答案 0 :(得分:5)

XOR n个数字就像计算每个位置的1位数,如果计数是奇数,则将相应的输出位设置为1。您XOR的顺序并不重要。

如果一个数组包含x对相等数字和一个唯一数字,则相等对的位相互抵消(因为它们在每个位置贡献偶数个1),只留下唯一数字的位

例如,请使用以下数字列表:

100100101
010110110
101101100 // the unique number
100100101
010110110

计算每个位置的1的数量:

321521522

XOR的结果(每个奇数计数为1位):

101101100 

这是列表中的唯一唯一编号。

答案 1 :(得分:5)

把它看作数学,而不是代码;使用^表示bit-level xor,我们可以说

  • xor是可交换的:A ^ B = B ^ A
  • xor是关联的:(A ^ B) ^ C = A ^ (B ^ C)
  • xoring with zero不执行任何操作:A ^ 0 = A
  • xoring两次删除它:A ^ A = 0

前两个属性意味着对x序列的任何重新排序都会产生完全相同的结果。

因此,给定一个包含重复项的序列,它们都将通过xor:

删除
   A ^ B ^ X ^ A ^ B  =  A^A ^ B^B ^ X  =  0 ^ 0 ^ X   =  X
                      \ reorder         \ xoring twice \ removing zeroes

请注意,只有当一个元素不重复时,此技巧才有效。如果有多个,结果将是所有非均匀重复元素的异或:

   A ^ B ^ C ^ A  =  A^A ^ B ^ C  =  B ^ C