给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
示例 1:
输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。
示例 2:
输入:nums = [-1,0]
输出:[-1,0]
示例 3:
输入:nums = [0,1]
输出:[1,0]
提示:
2 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
除两个只出现一次的整数外,nums 中的其他数字都出现两次
循环解法:
class Solution { public int[] singleNumber(int[] nums) { int[] target=new int[nums.length]; int index=0; int[] result=new int[2]; for(int i=0; i<nums.length;i++) { if (target[i]==2) { continue; } int temp=nums[i]; int flag=0; for(int j=i+1;j<nums.length;j++) { if (target[i]==2) { continue; } if(nums[j]==temp) { target[i]=2; target[j]=2; break; } } if(target[i]!=2) { result[index]=temp; index++; } } return result; } }
解题思路:先创建一个和给定数组大小一样的标志数组用来记录,各个元素出现的次数,初始化全部为0,另外创建一个新的result数组来存放最终结果。 两次遍历目标数组,首先判断当前元素的标志位是否为2,若为2说明出现了两次,直接跳过,否则继续往下走,依次遍历当前元素之后的元素进行对比,若有相同,则同时把两个元素的标志位置为2。 遍历结束后判断当前元素的标志位是否为2,若不为2则放入结果集。
大神进阶参考:
class Solution {
public int[] singleNumber(int[] nums) {
/**
有两个数只出现了一次记为 num1、num2 初始化为 0, 其余的数出现了两次,
我们可以对所有的数进行一次异或操作, 易知这个结果就等于 num1 和 num2
的异或结果(相同的数异或结果都为 0, 0和任意数异或结果都为那个数).
那么我可以考虑异或结果的某个非 0 位如最后一个非 0 位, 因为我们知道只
有当 num1、num2 在该位不一样的时候才会出现异或结果为 1. 所以我们以该
位是否为 1 对数组进行划分, 只要该位为 1 就和 num1 异或, 只要该位为 0
就和 num2 异或, 这样最终得到就是只出现过一次的两个数(其他在该位为 1 或
0 的数必然出现 0/2 次对异或结果无影响)
**/
int num1 = 0, num2 = 0;
int xor = 0;
for(int num : nums)
xor ^= num;
int bit_1 = 1;
while((xor & 1) == 0) {
xor >>= 1;
bit_1 <<= 1;
}
for(int num : nums) {
if((num & bit_1) == 0)
num1 ^= num;
else
num2 ^= num;
}
return new int[]{num1, num2};
}
}