Leetcode-136 只出现一次的数字

135 阅读2分钟

136. 只出现一次的数字

根据左神的数据结构和算法课程整理

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

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:
输入: [2,2,1]
输出: 1
​
示例 2:
输入: [4,1,2,1,2]
输出: 4

位运算的知识

基本概念:

  • 按位与 &:两位全为1,才为1,否则为0
  • 按位或 |:两位有一个为1,才为1,否则为0
  • 按位异或 ^:两位一个为1,一个为0时的结果为1,否则为0
  • 按位取反:0变为1,1变为0

如何计算:

  • 正数的原码首位为0,负数首位为1
  • 正数的原码、反码、补码都相同(三码合一)
  • 负数先算原码,原码首位为1,其余和其正数一样;然后计算其反码,也就是符号位(首位)不变,其他位取反,再算其补码,补码=反码+1
  • 结果按照补码计算后再变为源码

按位异或的一些公式:

//一个数与0异或,结果还为这个数
0 ^ a = a;
​
//一个数与1异或,结果为这个数的反码
1 ^ a = ~a;
​
//一个数与自己异或,结果为0
a ^ a = 0;
​
//按位异或满足交换律和结合律
a ^ b ^ c = a ^ (b ^ c);

有了这些知识就可以做这个题了。

解题思路

因为有一些数出现了两次,只有一个数出现了一次,那么把这些数都异或一遍,如果出现过两次,根据交换律,可以先让它们自己进行异或,那么结果为0,最后就只剩下0和出现一次的数进行异或,那么就剩下了这个数。

代码实现

public class SingleNumber {
    public static void main(String[] args){
        int[] arr = new int[]{1,1,2,2,2,2,3,3,3,3,3,3,4,4,4,4,5,5,5};
        System.out.println(SingleNumber.singleNumber(arr));
    }
​
​
    public static int singleNumber(int[] nums) {
        int eor = 0;
        for (int i = 0; i < nums.length; i++) {
            eor = eor ^ nums[i];
        }
        return eor;
    }
}