[leetCode]剑指 Offer 56 - II. 数组中数字出现的次数 I、II
解法
有两个数字只出现一次,其余数字出现两次,那么出现两次的数字异或之后为0相互抵消,剩下两个出现一次的数字由于一定不相同,所以异或之后肯定有一位为1。所以可以通过该位是否为1将数组划分为两个子数组,每个数字都只有一个数字出现一次,这样就能通过异或分别找到每个数组中只出现一次的数字了。
class Solution {
public int[] singleNumbers(int[] nums) {
if (nums == null) return null;
if (nums.length < 2) return new int[]{nums[0],0};
int resultExclusiveOR = 0;
for (int i = 0; i < nums.length; i ++)
resultExclusiveOR ^= nums[i];
int indexOf1 = findFirstBitIs1(resultExclusiveOR);
int[] ans = new int[2];
for (int i = 0; i < nums.length; i++) {
if (isBit1(nums[i], indexOf1)) {
ans[0] ^= nums[i];
} else {
ans[1] ^= nums[i];
}
}
return ans;
}
private int findFirstBitIs1(int num) {
int indexBit = 0;
while (((num & 1) == 0) && (indexBit < 32)) {
num = num >> 1;
++indexBit;
}
return indexBit;
}
private boolean isBit1(int num, int index) {
num = num >> index;
return ((num & 1) == 1);
}
}
解法
由于除了只出现一次的数字之外其余数字都出现三次,那么把出现三次的数字每一位加起来肯定能被3整除。所以我们可以把数组中所有的数字每一位都加起来,如果某一位能被3整除则说明只出现一次的数字在该位为0,否则为1。
class Solution {
public int singleNumber(int[] nums) {
if (nums == null || nums.length == 0) return 0;
// 长度为32的辅助数组,用于记录数字每一位的和
int[] bitSum = new int[32];
for (int i = 0; i < nums.length; i++) {
int bitMask = 1;
for (int j = 31; j >= 0; j--) {
int bit = nums[i] & bitMask;
if (bit != 0) {
++bitSum[j];
}
bitMask = bitMask << 1;
}
}
int result = 0;
for (int i = 0; i < 32; i++) {
result = result << 1;
result += bitSum[i] % 3;
}
return result;
}
}
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
【推荐】AI 的力量,开发者的翅膀:欢迎使用 AI 原生开发工具 TRAE
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
· 记一次 C# 平台调用中因非托管 union 类型导致的内存访问越界
· [EF Core]聊聊“复合”属性
· 那些被推迟的 C# 14 特性及其背后的故事
· 我最喜欢的 C# 14 新特性
· 程序员究竟要不要写文章
· 我是不是很有钱?
· 遭遇疯狂 cc 攻击的一个周末
· 【EF Core】聊聊“复合”属性
· GPT‑5 重磅发布
· 美丽而脆弱的天体运动:当C#遇见宇宙混沌