【力扣-算法面试汇总】1、只出现一次的数字

145 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

【说明】

算法应该具有线性时间复杂度。 不使用额外空间来实现

  • 示例 1:

    输入: [2,2,1]

    输出: 1

  • 示例 2:

    输入: [4,1,2,1,2]

    输出: 4

来源:LeetCode

原则:先暴力,后方法优化

【暴力法】

// java
class Solution {
    public int singleNumber(int[] nums) {
        // 判断数组是否只有一个元素
        if(nums.length == 1){
            return nums[0];
        }
        // 对数组进行排序
        Arrays.sort(nums);
        // 判断排序后的前两个数字是否不同
        if(nums[0]!=nums[1]){
            return nums[0];
        }
        int len = nums.length;
        // 判断排序后最后两个数字是否不同
        if(nums[len-1] !=nums[len-2]){
            return nums[len-1];
        }
        int res = 0 ; 
        // 判断中间部分的数字与两边的数字是否都不相同
        for(int i = 1;i<len-1;i++){
            if(nums[i]!=nums[i-1] && nums[i]!=nums[i+1]){
                res = nums[i];
                break;
            }
        }
        return res;
    }
}

【位运算】

使用异或运算,不同为1,相同为0。

0与任意数n取异或的结果仍为n,所以最后就只剩一个数。

异或满足以下规律:

  • 1、归零率: n ^ n = 0
  • 2、恒等率: n ^ 0 = n
  • 3、交换律: n ^ m = m ^ n
  • 4、结合率:n ^ m ^ i = n ^ (m^i) = (n^m) ^ i
  • 5、自反: n ^ m ^ n = m
  • 6、由 x = y ^ z ^ w 可以推出 w = x ^ y ^ z
// java
class Solution {
    public int singleNumber(int[] nums) {
        int res = 0 ;
        // 可以先进行排序,排序后,利用结合率
        // 相同的异或为0 , 
        // 最后 0 与单独的数异或,结果还是那个数
        for(int i = 0 ; i< nums.length ; i++){
            // 0 与 nums[i] 异或的结果仍为nums[i]
            // nums[i] 与 nums[i+1] 取异或,
            // 若相同,则 res = 0 ;
            // 若不同,则 res = 1 ;
            res = res ^ nums[i];
        }
        // 返回单独的数
        return res;
    }
}