數組中只出現一次的數
阿新 • • 發佈:2017-11-30
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; } }
數組中只出現一次的數