1、解题思路
- 异或法:将所有数字进行异或,最终得到的结果是两个只出现一次的数字的异或结果。找到异或结果中的任意一个为1的位,该位可以将数组分成两部分,每部分各包含一个只出现一次的数字。对这两部分分别进行异或,得到两个只出现一次的数字。时间复杂度:O(n),空间复杂度:O(1)。
- 哈希表法:使用哈希表统计每个数字的出现次数。遍历哈希表,找到出现次数为1的数字。时间复杂度:O(n),空间复杂度:O(n)。不符合题目对空间复杂度 O(1) 的要求。
- 排序法:将数组排序,然后遍历数组找到只出现一次的数字。时间复杂度:O(nlogn),空间复杂度:O(1)。不符合题目对时间复杂度 O(n) 的要求。
2、代码实现
C++
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型vector
*/
vector<int> FindNumsAppearOnce(vector<int>& nums) {
// write code here
int xorResult = 0;
for (int num : nums) {
xorResult ^= num;
}
int diffBit = 1;
while ((xorResult & diffBit) == 0) {
diffBit <<= 1;
}
int num1 = 0, num2 = 0;
for (int num : nums) {
if ((num & diffBit) == 0) {
num1 ^= num;
} else {
num2 ^= num;
}
}
if (num1 > num2) {
swap(num1, num2);
}
return {num1, num2};
}
};
Java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型一维数组
*/
public int[] FindNumsAppearOnce (int[] nums) {
// write code here
int xorResult = 0;
for (int num : nums) {
xorResult ^= num;
}
int diffBit = 1;
while ((xorResult & diffBit) == 0) {
diffBit <<= 1;
}
int num1 = 0, num2 = 0;
for (int num : nums) {
if ((num & diffBit) == 0) {
num1 ^= num;
} else {
num2 ^= num;
}
}
if (num1 > num2) {
int temp = num1;
num1 = num2;
num2 = temp;
}
return new int[]{num1, num2};
}
}
Python
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @return int整型一维数组
#
class Solution:
def FindNumsAppearOnce(self , nums: List[int]) -> List[int]:
# write code here
xor_result = 0
for num in nums:
xor_result ^= num
diff_bit = 1
while (xor_result & diff_bit) == 0:
diff_bit <<= 1
num1, num2 = 0, 0
for num in nums:
if (num & diff_bit) == 0:
num1 ^= num
else:
num2 ^= num
return [num1, num2] if num1 < num2 else [num2, num1]
3、复杂度分析
- 异或法的核心思想:
异或操作的性质:任何数字异或自己结果为0,异或0结果为自身。将所有数字异或后,得到的结果是两个只出现一次的数字的异或结果。通过找到异或结果中的任意一个为1的位,可以将数组分成两部分,每部分各包含一个只出现一次的数字。
- 效率:
时间复杂度:O(n),因为只需要遍历数组两次(一次计算异或结果,一次分组异或)。空间复杂度:O(1),仅需常数级别的额外空间。