1. 程式人生 > >數組中只出現一次的數

數組中只出現一次的數

while col 思路 整數 static 對數 num sys 題目

  問題一:在一個整數數組中,除了一個數之外,其他的數出現的次數都是兩次,求出現一次的數,要求時間復雜度盡可能的小。例如數組{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;
    }
}

數組中只出現一次的數