美文网首页剑指offer的java实现-数据结构与算法
剑指offer第二版-56.数组中只出现一次的两个数字

剑指offer第二版-56.数组中只出现一次的两个数字

作者: ryderchan | 来源:发表于2017-09-05 15:16 被阅读262次

    本系列导航:剑指offer(第二版)java实现导航帖

    面试题56:数组中只出现一次的两个数字

    题目要求:
    一个整数数组里除了两个数字出现一次,其他数字都出现两次。请找出这两个数字。要求时间复杂度为o(n),空间复杂度为o(1)。

    解题思路:
    这道题可以看成“数组中只出现一次的一个数字”的延伸。如果所有数字都出现两次,只有一个数字是出现1次,那么可以通过把所有所有进行异或运算解决。因为x^x = 0。
    但如果有两个数字出现一次,能否转化成上述问题?依旧把所有数字异或,最终的结果就是那两个出现一次的数字a,b异或的结果。因为a,b不想等,因此结果肯定不为0,那么结果的二进制表示至少有一位为1,找到那个1的位置p,然后我们就可以根据第p位是否为1将所有的数字分成两堆,这样我们就把所有数字分成两部分,且每部分都是只包含一个只出现一次的数字、其他数字出现两次,从而将问题转化为最开始我们讨论的“数组中只出现一次的一个数字”问题。

    实例分析(以2,4,3,6,3,2,5,5为例):

    相关数字的二进制表示为:
    2 = 0010       3 = 0011       4 = 0100
    5 = 0101       6 = 0110
    
    步骤1 全体异或:2^4^3^6^3^2^5^5 = 4^6 = 0010
    步骤2 确定位置:对于0010,从右数的第二位为1,因此可以根据倒数第2位是否为1进行分组
    步骤3 进行分组:分成[2,3,6,3,2]和[4,5,5]两组
    步骤4 分组异或:2^3^6^3^2 = 6,4^5^5 = 4,因此结果为4,6。
    

    代码实现:

    package chapter6;
    
    /**
     * Created with IntelliJ IDEA
     * Author: ryder
     * Date  : 2017/8/17
     * Time  : 10:58
     * Description:数组中数字出现的次数
     * 有两个数字分别出现一次,其他的都出现两次,找到这两个数字
     **/
    public class P275_NumberAppearOnce {
        public static int[] findNumsAppearOnce(int[] data){
            int result = 0;
            for(int i=0;i<data.length;i++)
                result^=data[i];
            int indexOf1 = findFirstBit1(result);
            int ret[] = new int[]{0,0};
            if(indexOf1<0)
                return ret;
            for(int i=0;i<data.length;i++){
                if((data[i]&indexOf1)==0)
                    ret[0]^=data[i];
                else
                    ret[1]^=data[i];
            }
            return ret;
        }
        public static int findFirstBit1(int num){
            if(num<0)
                return -1;
            int indexOf1 = 1;
            while (num!=0){
                if((num&1)==1)
                    return indexOf1;
                else{
                    num = num>>1;
                    indexOf1*=2;
                }
            }
            return -1;
        }
        public static void main(String[] args){
            int[] data = new int[]{2,4,3,6,3,2,5,5};
            int[] result = findNumsAppearOnce(data); // 4,6
            System.out.println(result[0]);
            System.out.println(result[1]);
    
        }
    }
    
    

    运行结果

    4
    6
    

    相关文章

      网友评论

        本文标题:剑指offer第二版-56.数组中只出现一次的两个数字

        本文链接:https://www.haomeiwen.com/subject/xnohjxtx.html