剑指offer-数组中只出现一次的数字

36 篇文章 0 订阅
8 篇文章 0 订阅

数组中只出现一次的数字

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

分析:

  • 相信大家对数组中只有一个数字对出现一次,其他都出现2次的题目(算法)都清楚,嗯,对,就是异或。
/**
* 数组a中只有一个数出现一次,其他数都出现了2次,找出这个数字
* @param a
* @return
*/
public static int find1From2(int[] a){
   int len = a.length, res = 0;
   for(int i = 0; i < len; i++){
       res = res ^ a[i];
   }
   return res;
}
  • 然而此题是一个变种,再把全部数字异或得到的值为那两个数的异或值,无法得到单个元素值,此时感觉没法走下去了,别急,既然异或可以求出单个元素的情况,那么我们是否可以把原来的数组分组呢?只要把这两个不同的数分到不同组,再异或,就得到了值。额,是的,有的头绪了,慢着?那总得分组依据吧。。。额,又傻了是不是。。。仔细想下,第一个问题求出了两个不同数的异或值,我们知道不同的数异或值一定不等于0,即异或值位中最少有一个1,且这个1= 0^1 得到的,在这个位上那两个数是不同的,因此分组依据就清楚咯。下面直接看代码。
/**
     * 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
     * num1,num2分别为长度为1的数组。传出参数
     * 将num1[0],num2[0]设置为返回结果
     * @param array
     * @param num1
     * @param num2
     */
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if (array == null || array.length <= 1) {
            return;
        }
        int a = 0;
        for (int i = 0;i<array.length;i++) {
            a = array[i]^a;
        }
        int index = 0;
        while ((a & 1) == 0) { //从右到左,寻找第一位为1的位
            a = a >> 1;
            index++;
        }
        for (int i =0;i<array.length;i++) {
            if (isIndexBit(array[i], index)) {
                num1[0] ^= array[i];
            }else{
                num2[0] ^= array[i];
            }
        }
    }

    private boolean isIndexBit(int num, int index) {
        num = num>>index;
        return (num & 1) == 1;
    }

至此,问题已经解决了。。。

  • 扩展问题: 数组a中只有一个数出现一次,其他数字都出现了3次,找出这个数字,这个问题,也需要点技巧,将每个位为1的个数统计出来,最后判断,如果这个为个数为3的倍数,那么这个数此位为0,否则为1,通过位移以及或运算可以求得这个数。
    /**
     * 数组a中只有一个数出现一次,其他数字都出现了3次,找出这个数字
     * @param a
     * @return
     */
    public static int find1From3(int[] a){
        int[] bits = new int[32];
        int len = a.length;
        for(int i = 0; i < len; i++){
            for(int j = 0; j < 32; j++){
                bits[j] = bits[j] + ( (a[i]>>>j) & 1);
            }
        }
        int res = 0;
        for(int i = 0; i < 32; i++){
            if(bits[i] % 3 !=0){
                res = res | (1 << i);
            }
        }
        return res;
    }

至此,问题才能说是圆满解决了!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值