链接
牛客:数组中只出现一次的数字
LeetCode:剑指 Offer 56 - I. 数组中数字出现的次数
思路
我们知道,偶数个数字做异或结果都是 0,0 和任意一个数字异或结果都是那个数字,数组中只存在两个出现一次的数字,别的数字都出现偶数次,我们从头到位对数组做异或运算,得到的最终结果应该是两个不同数字做异或运算后的值。
因为两个数字不相同,最终的结果也肯定不是0,且结果对应的二进制位中至少有一个为1,我们找到二进制位中第一个是 1 的位置,即为 n,然后根据地 n 为是 1 还是 0 把数组分为两个子数组,第一个子数组中的每个数的二进制位的第 n 位都是 1,另外一个是 0,这样分完后,相同的数字肯定会被分到同一个子数组中,并且每个子数组中只包含一个只出现一次的数,我们可以继续异或两个子数组,最后得到的两个数就是只出现一次的数字。
代码
牛客:
public class Solution {
public static void FindNumsAppearOnce(int[] array, int[] num1, int[] num2) {
int len = array.length;
if (len < 2)
return;
if (len == 2) {
num1[0] = array[0];
num2[0] = array[1];
}
int resultOr = 0;
for (int i = 0; i < len; i++) {
resultOr ^= array[i];
}
int indexOf = findFirstBit(resultOr);
num1[0] = num2[0] = 0;
for (int j = 0; j < len; j++) {
if (isBit1(array[j], indexOf) == 1) {
num1[0] ^= array[j];
} else {
num2[0] ^= array[j];
}
}
}
//找到从右向左第一个位为1的下标indexBit
public static int findFirstBit(int num) {
int indexBit = 0;
while ((num & 1) == 0) {
num = num >> 1;
indexBit++;
}
return indexBit;
}
//找到第indexBit位是否为1
public static int isBit1(int num, int indexBit) {
num = num >> indexBit;
return (num & 1);
}
}
LeetCode:
class Solution {
public int[] singleNumbers(int[] nums) {
int[] result = new int[2];
int len = nums.length;
if (len < 2)
return null;
if (len == 2) {
result[0] = nums[0];
result[1] = nums[1];
}
int resultOr = 0;
for (int i = 0; i < len; i++) {
resultOr ^= nums[i];
}
int indexOf = findFirstBit(resultOr);
result[0] = result[1] = 0;
for (int j = 0; j < len; j++) {
if (isBit1(nums[j], indexOf) == 1) {
result[0] ^= nums[j];
} else {
result[1] ^= nums[j];
}
}
return result;
}
//找到从右向左第一个位为1的下标indexBit
public static int findFirstBit(int num) {
int indexBit = 0;
while ((num & 1) == 0) {
num = num >> 1;
indexBit++;
}
return indexBit;
}
//找到第indexBit位是否为1
public static int isBit1(int num, int indexBit) {
num = num >> indexBit;
return (num & 1);
}
}