1、解题思路

  1. 异或法:将所有数字进行异或,最终得到的结果是两个只出现一次的数字的异或结果。找到异或结果中的任意一个为1的位,该位可以将数组分成两部分,每部分各包含一个只出现一次的数字。对这两部分分别进行异或,得到两个只出现一次的数字。时间复杂度:O(n),空间复杂度:O(1)。
  2. 哈希表法:使用哈希表统计每个数字的出现次数。遍历哈希表,找到出现次数为1的数字。时间复杂度:O(n),空间复杂度:O(n)。不符合题目对空间复杂度 O(1) 的要求。
  3. 排序法:将数组排序,然后遍历数组找到只出现一次的数字。时间复杂度: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、复杂度分析

  1. 异或法的核心思想: 异或操作的性质:任何数字异或自己结果为0,异或0结果为自身。将所有数字异或后,得到的结果是两个只出现一次的数字的异或结果。通过找到异或结果中的任意一个为1的位,可以将数组分成两部分,每部分各包含一个只出现一次的数字。
  2. 效率: 时间复杂度:O(n),因为只需要遍历数组两次(一次计算异或结果,一次分组异或)。空间复杂度:O(1),仅需常数级别的额外空间。