zoukankan      html  css  js  c++  java
  • 数组中只出现一次的数

      问题一:在一个整数数组中,除了一个数之外,其他的数出现的次数都是两次,求出现一次的数,要求时间复杂度尽可能的小。例如数组{1,2,2,3,3,6,6},出现一次的数是1.

      从题目的描述可以看出,数组中只有一个数字出现了一次,其他的数字都出现两次,联想到异或运算的特点:任何一个数字和自己做异或运算的结果都是0,任何数字和0运算的结果都是本身。根据上述特点,可以考虑从数组的第一个元素开始,逐个和后面的元素做异或操作,最后的计算结果就是要找的只出现一次的数。

      算法实现如下:  

    public class Main {
    
        public static void main(String[] args){
            int[] nums = new int[]{1,2,2,3,3,4,4,1,23};
            System.out.println(getNumAppearsOnce(nums));
        }
    
        public static int getNumAppearsOnce(int[] nums){
    
            if(nums == null || nums.length <= 2){
                throw new IllegalArgumentException("nums size must bigger than 2");
            }
    
            int result = 0;
            for(int i=0;i<nums.length;i++){
                result ^= nums[i];
            }
    
            return result;
        }
    }

      由于只需要遍历一遍数组就可以找到结果,因此上述算法的时间复杂度为O(N),其中N为数组的长度

    发散思维:假如要求的数组里面有两个数出现的次数是1,其他出现的次数都是2,如何找出这两个数呢?

      根据上面问题一的思路,我们依然从头到位对数组做异或运算,得到的最终结果应该是两个不同数字做异或运算后的值。因为两个数字不相同,最终的结果也肯定不是0,切结果对应的二进制位中至少有一个为1,我们找到二进制位中第一个是1的位置,即为n,然后根据地n为是1还是0把数组分为两个子数组,第一个子数组中的每个数的二进制位的第n位都是1,另外一个是0,这样分完后,相同的数字肯定会被分到同一个子数组中,并且每个子数组中只包含一个只出现一次的数,根据问题一,我们可以很方便的求出两个只出现一次的数,实现如下:

    public class Main {
    
        public static void main(String[] args){
            int[] nums = new int[]{1,2,2,3,3,4,4,1,23,43};
            System.out.println(getNumsAppearsOnce(nums));
        }
    
        public static int getNumAppearsOnce(int[] nums){
    
            if(nums == null || nums.length <= 2){
                throw new IllegalArgumentException("nums size must bigger than 2");
            }
    
            int result = 0;
            for(int i=0;i<nums.length;i++){
                result ^= nums[i];
            }
    
            return result;
        }
    
        public static List<Integer> getNumsAppearsOnce(int[] nums){
    
            if(nums == null || nums.length <= 2){
                throw new IllegalArgumentException("nums size must bigger than 2");
            }
    
            List<Integer> result = new ArrayList<Integer>(2);
            int temp = getNumAppearsOnce(nums);
    
            int index = findFirstBitIdOne(temp);
            int num1 = 0,num2 = 0;
    
            for(int i=0;i<nums.length;i++){
                if(isBitOne(nums[i],index)){
                    num1 ^= nums[i];
                }else{
                    num2 ^= nums[i];
                }
            }
    
            result.add(num1);
            result.add(num2);
            return result;
        }
    
        private static boolean isBitOne(int num, int index) {
            num = num >> index;
            return (num & 1) == 1;
        }
    
        private static int findFirstBitIdOne(int temp) {
            int index = 0;
            while((temp & 1) == 0){
                temp =  temp >> 1;
                index++;
            }
            return index;
        }
    }
  • 相关阅读:
    [bbk2342] 第47集 Chapter 09Optimizing Sore Perations(02)
    [bbk2345] 第50集 Chapter 12Optimizing Sore Perations(05)
    [bbk2343] 第48集 Chapter 12Optimizing Sore Perations(03)
    [bbk2863] 第54集 Chapter 14Using Oracle Dasta Storage Structures Efficiently(00)
    [bbk2515] 第51集 Chapter 13Using Oracle Blokcs Efficeintly[00]
    [bbk2341] 第46集 Chapter 09Optimizing Sore Perations(01)
    [bbk2863] 第54集 Chapter 13Using Oracle Blokcs Efficeintly[03]
    [bbk2668] 第53集 Chapter 13Using Oracle Blokcs Efficeintly[02]
    [bbk2344] 第49集 Chapter 12Optimizing Sore Perations(04)
    QT 中的模态和非模态对话框
  • 原文地址:https://www.cnblogs.com/senlinyang/p/7930417.html
Copyright © 2011-2022 走看看