使用位运算查找只出现一次的数字
一个数组中只有一个数字出现一次,其他数字都出现两次,请找出这个数字
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for (int num : nums) {
res ^= num;
}
return res;
}
public static void main(String[] args) {
System.out.println(new Solution().singleNumber(new int[]{2, 2, 1}));
System.out.println(5);
}
}
leetcode-136. 只出现一次的数字
异或运算有以下性质
a^0=a 任何数异或0等于自身
a^a=0 任何数和自身异或等于0
a^b^a=a^(b^a)=(a^a)^b=b 满足交换律和结合律
以数组[2,2,1]为例,1^2^1=1^1^2=0^2=2
一个数组中只有两个数字出现一次,其他所有数字都出现了两次,请找出这两个数字
import java.util.Arrays;
class Solution {
public int[] singleNumber(int[] nums) {
int xorRes = 0;
for (int num : nums) {
xorRes ^= num;
}
//找到第一位不为0的位数,如6 pos为1
int pos = 0;
while (((xorRes >> pos) & 1) == 0) {
pos++;
}
//分组异或 分为pos位为0的和pos位为1的
int res1 = 0;
int res2 = 0;
for (int num : nums) {
if (((num >> pos) & 1) == 0) {
res1 ^= num;
} else {
res2 ^= num;
}
}
return new int[]{res1, res2};
}
public static void main(String[] args) {
int[] res = new Solution().singleNumber(new int[]{1, 2, 1, 3, 2, 284593787});
System.out.println(Arrays.toString(res));
}
}
leetcode-260. 只出现一次的数字 III
先对所有数字进行一次异或,结果为两个出现一次数字的异或值,得到第一个为1的位的位置,根据这一位是否为1,将所有数字分成两组:
- 两个只出现一次的数字分在不同的组中
- 相同的数字分在相同的组中
分别对每一组进行异或即可得到答案,以数组[1,2,3,1,2,5]为例,第一次异或之后得到6,二进制表示为000...0110,第一个为1的位的位置为1,根据这一位分组。
一个数组中只有一个数字出现一次,其他数字都出现三次,请找出这个数字
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for (int i = 0; i < 32; i++) {
int bitSum = 0;
for (int num : nums) {
bitSum += (num >> i) & 1;
}
res += (bitSum % 3) << i;
}
return res;
}
public static void main(String[] args) {
System.out.println(new Solution().singleNumber(new int[]{2, 2, 3, 5, 3, 3, 2}));
}
}
leetcode-137. 只出现一次的数字 II
对所有数字,统计每一位的个数,对3取模,以数组[2,2,2,5]为例,统计得到第0位个数1,第1位个数3,第二位个数1,转成十进制为
1<<2 + 0<<0 + 1<<1 = 5