数组中只出现一次的数字

第三十九题:数组中只出现一次的数字

    • 题目描述
    • 思路
        • hash表解:
            • hash表解(代码实现):
        • 异或运算:
            • 具体实现如下图所示:
            • 具体实现代码如下:


题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。


思路

hash表解:

将元素都存入hash表,我们会发现只有两个数出现1次


hash表解(代码实现):
// hash
public class Solution {
	public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
		if(array==null&&array.length<=1){
			num1[0]=num2[0]=0;
			return;
		}
		HashMap<Integer,Integer> map = new HashMap<>();
		for(int i=0;i<array.length;i++){
			if(map.containsKey(array[i])){
				map.put(array[i],2);
			}else{
                		map.put(array[i],1);
            		}
       		 }
       		 num1[0]=0;
        	for(Entry entry:map.entrySet()){
        		if((Integer)entry.getValue()==1){
        			if(num1[0]==0){
        				num1[0]=(Integer)entry.getKey();
                		}else{
                    			num2[0]=(Integer)entry.getKey();
                		}
            		}
        	}
    	}
}

异或运算:

这里说明暴力解,原理跟选择排序一样
前面两种解法只是在做铺垫, 暴力解  T(N) = O(N^2) S(N) = O(1)  太耗时
                       hash表 T(N) = O(N)   S(N) = O(N)  太耗空间
先了解一下异或运算的性质:
    两个相同数字异或=0,一个数和0异或还是它本身
运算规则:
	0^0=0;   0^1=1;   1^0=1;   1^1=0;
利用这个性质我们不难发现,如果数组中只有一个数出现一次,那么我们至于要进行一遍异或运算就能得到这个出现一次的数
但是数组中有两个数出现一次的数,进行一遍异或运算后,我们得到的是两个出现一次数字的异或运算结果
这个异或结果说明什么?看下面例子
array[1,1,2,2,3,3,4,5]

具体实现如下图所示:

数组中只出现一次的数字_第1张图片


具体实现代码如下:
// num1,num2分别为长度为1的数组。传出参数
// 将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        // 代码的鲁棒性
        if (array == null || array.length < 2){
            return;
        }
        // 异或的结果
        int res = 0;
        for (int i : array) {
            res ^= i;
        }
        // 找不同
        int index = findFirstIndex(res);
        num1[0] = 0;
        num2[0] = 0;
        // 这里就是指的切分数组的操作,但实际上我们并不用去切分,而是直接进行异或操作就好
        for (int i = 0; i < array.length;i++){
            if (isBit(array[i],index)){
                num1[0] ^= array[i];
            }else {
                num2[0] ^= array[i];
            }
        }
    }

    // 二进制数 从右往左 找到第一个 "1"
    public int findFirstIndex(int n) {
        int index = 0;
        while ((1&n) == 0 && index < 4*8){
            n = n >> 1;
            index++;
        }
        return index;
    }

    // 判断这个数的二进制形式从左到右index位是否为"1"
    public boolean isBit(int num, int index){
        boolean flag = false;
        num = num >> index;
        if ((num&1) == 1){
            flag = true;
        }
        return flag;
    }
}

NowCoder(Online Coding, Please Click)

你可能感兴趣的:(剑指offer,剑指offer)