題目連接數組
題目大意:給出一串數組,裏面的數都是兩個,只有一個數是一個,把這個只有一個的數找出來。時間複雜度最好是線性的,空間複雜度最好爲O(1).ide
法一:利用map,空間換時間,代碼以下(耗時26ms):spa
1 public int singleNumber(int[] nums) { 2 Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 3 int res = -1; 4 for(int i = 0; i < nums.length; i++) { 5 if(map.get(nums[i]) != null && map.get(nums[i]) == 1) { 6 map.put(nums[i], 2); 7 } 8 else { 9 map.put(nums[i], 1); 10 } 11 } 12 for(int i = 0; i < nums.length; i++) { 13 if(map.get(nums[i]) == 1) { 14 res = nums[i]; 15 break; 16 } 17 } 18 return res; 19 }
法二:先排序,再一個for循環,依次比較,代碼以下(耗時8ms):code
1 public int singleNumber(int[] nums) { 2 Arrays.sort(nums); 3 int res = nums[0]; 4 int cnt = 1; 5 boolean flag = false; 6 for(int i = 1; i < nums.length; i++) { 7 if(nums[i] != nums[i - 1]) { 8 if(cnt == 1) { 9 res = nums[i - 1]; 10 flag = true; 11 break; 12 } 13 cnt = 1; 14 } 15 else { 16 cnt++; 17 } 18 } 19 if(flag == false) { 20 res = nums[nums.length - 1]; 21 } 22 return res; 23 }
法三(借鑑):利用異或,由3^3=0知道,相同的兩個數異或爲0,不一樣的兩個數異或爲1。代碼以下(耗時1ms):blog
1 public int singleNumber(int[] nums) { 2 int res = nums[0]; 3 for(int i = 1; i < nums.length; i++) { 4 res = res ^ nums[i]; 5 } 6 return res; 7 }
法四(借鑑):利用137題的法三,位運算,只是把對3取模改爲對2取模便可。(num>>i)&1取num的第i位二進制數。ans |= sum <<i將二進制相加轉爲十進制。代碼以下(耗時12ms):排序
1 public int singleNumber(int[] nums) { 2 int ans = 0; 3 int length = nums.length; 4 //將每個數取二進制位按位相加,若是都是重複的則當前位的相加和必定是3的倍數,不然當前位必定存在於要找的那個數中 5 //好比1,1,1,2,2,2,3這六個數將其轉爲二進制數按位相加,而後每一位都對3取模,最後必定能夠獲得3 6 for(int i = 0; i < 32; i++) {//計算每一位 7 int sum = 0;//統計每一位的和 8 for(int j = 0; j < length; j++) {//對每一個數取第i位的數值 9 if(((nums[j] >> i) & 1) == 1) {//取第i位的數值 10 sum++;//將每一個數第i位的值相加求和 11 sum %= 2; 12 } 13 } 14 if(sum != 0) {//若是對3取模後非0,則說明當前位必定是要找的數的某一位 15 ans |= sum << i;//將其轉爲十進制加入結果當中 16 } 17 } 18 return ans; 19 }