zoukankan      html  css  js  c++  java
  • 剑指Offer对答如流系列

    面试题56:数组中数字出现的次数

    题目描述

    问题(1)数组中只出现一次的两个数字

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

    问题(2)数组中唯一只出现一次的数字

    在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

    问题分析

    问题(1)分析

    在这篇文章剑指Offer对答如流系列 - 二进制中 1 的个数中,我们详细探讨了位运算,其中有重要的一条:两个相同的数异或的结果是 0,一个数和 0 异或的结果是它本身

    如果数组中只有一个数字只出现一次,我们从头到尾异或每个数字,那么最终的结果刚好是那个只出现一次的数字。

    本题里数组中有两个数字只出现一次,所以要做一些处理:

    1. 我们依旧从头到尾异或每个数字,最终的结果就是这两个只出现一次的数字的异或结果,由于两个数不同,结果数字中一定有一位为1,把结果中第一个为1的位置记为第n位。由于是两个只出现一次的数字的异或结果,因此这两个数字在第n位上的数字一定是1和0。

    2. 接下来根据数组中每个数字的第n位上的数字是否为1来进行分组,恰好能将数组分为两个都只有一个数字只出现一次的数组,对两个数组从头到尾异或,就可以得到这两个数了。

    问题(2)分析

    数字出现了三次,不能直接利用异或位运算进行消除相同个数字。但是仍然可以沿用位运算的思路。

    将所有数字的二进制表示的对应位都加起来,如果某一位能被三整除,那么只出现一次的数字在该位为0;反之,为1。

    问题解答

    问题(1)

      public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
    
            if(array==null || array.length<2) {
                return;
            }
            int resultExclusiveOR=0;
            for(int i=0;i<array.length;i++) {
                resultExclusiveOR^=array[i];
            }
    
            int indexOf1=0;
            while(((resultExclusiveOR&1) == 0) && (indexOf1 <= 32)){
                //易错点:只有n>>1不完整,要n=n>>1
                resultExclusiveOR = resultExclusiveOR>>1;
                indexOf1++;
            }
    
            num1[0]=0;
            num2[0]=0;
            for(int i=0;i<array.length;i++){
                if(((array[i]>>indexOf1)&1) == 1) {
                    num1[0]^=array[i];
                } else {
                    num2[0]^=array[i];
                }
            }
        }
    

    问题(2)

        public  int findNumberAppearingOnce(int[] arr) {
            if(arr==null || arr.length<=0) {
                throw new RuntimeException();
            }
            
            int[] bitSum = new int[32];
            Arrays.fill(bitSum, 0);
    
            for(int i=0;i<arr.length;i++) {
                int bitMask=1;
                for(int j=31; j>=0; j--) {
    
                    int bit= arr[i]&bitMask;
                    if(bit!=0) {
                        bitSum[j]+=1;
                    }
                    bitMask=bitMask<<1;
                }
            }
            int result=0;
            for(int i=0;i<32;i++) {
                result=result<<1;
                result+=(bitSum[i]%3);
            }
            return result;
        }
    
  • 相关阅读:
    测试
    vue项目中使用 SheetJS / js-xlsx 导入文件
    vue项目中使用 SheetJS / js-xlsx 导出文件
    vue项目中使用canvas
    uniapp中mqtt的基本使用
    uniapp中vuex的基本使用
    uniapp如何在当前页面获取上个页面的变量、方法
    “微信小程序从分享卡片进入,第一次获取不到用户uid、第二次能获取到用户uid”解决方法
    vue-router的安装和使用
    vue-cli的安装步骤
  • 原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246898.html
Copyright © 2011-2022 走看看