137.Single Number II---位運算---《劍指offer》40

題目連接:https://leetcode.com/problems/single-number-ii/description/html

題目大意:給出一串數,每一個數都出現三次,只有一個數只出現一次,把這個出現一次的數找出來。數組

法一:利用hashMap,空間換時間,可是好像也沒怎麼換到時間。代碼以下(耗時15ms):ide

 1     public int singleNumber(int[] nums) {
 2         Map<Integer, Integer> map = new HashMap<Integer, Integer>();
 3         int ans = -1;
 4         for(int i = 0; i < nums.length; i++) {
 5             if(map.containsKey(nums[i])) {
 6                 map.put(nums[i], map.get(nums[i]) + 1);
 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                 ans = nums[i];
15                 break;
16             }
17         }
18         return ans;
19     }
View Code

法二:先排序,再一一計算。代碼以下(耗時5ms):spa

 1     public int singleNumber(int[] nums) {
 2         Arrays.sort(nums);
 3         int ans = nums[0];
 4         int cnt = 1;
 5         int length = nums.length;
 6         for(int i = 1; i < length; i++) {
 7             if(nums[i] != nums[i - 1]) {
 8                 if(cnt == 1) {
 9                     break;
10                 }
11                 ans = nums[i];
12                 cnt = 1;
13             }
14             else {
15                 cnt++;
16             }
17         }
18         return ans;
19     }
View Code

法三(借鑑):利用位運算,這個方法是廣泛方法,136題也能夠用這個方法作,可是時間複雜度實際上是o(n^2),因此也不是最優的,只是用到了位運算。借鑑自:http://blog.csdn.net/feliciafay/article/details/19004479。代碼以下(耗時7ms):.net

 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 %= 3;
12                 }
13             }
14             if(sum != 0) {//若是對3取模後非0,則說明當前位必定是要找的數的某一位
15                 ans |= sum << i;//將其轉爲十進制加入結果當中
16             }
17         }
18         return ans;
19     }
View Code

法四(借鑑):這個位運算還沒看懂。https://www.cnblogs.com/yangrouchuan/p/5323327.htmlcode

 

 1 連接:https://www.nowcoder.com/questionTerminal/e02fdb54d7524710a7d664d082bb7811
 2 來源:牛客網
 3 
 4 /**
 5      * 數組中有兩個出現一次的數字,其餘數字都出現兩次,找出這兩個數字
 6      * @param array
 7      * @param num1
 8      * @param num2
 9      */
10     public static void findNumsAppearOnce(int [] array,int num1[] , int num2[]) {
11         if(array == null || array.length <= 1){
12             num1[0] = num2[0] = 0;
13             return;
14         }
15         int len = array.length, index = 0, sum = 0;
16         for(int i = 0; i < len; i++){
17             sum ^= array[i];
18         }
19         for(index = 0; index < 32; index++){
20             if((sum & (1 << index)) != 0) break;
21         }
22         for(int i = 0; i < len; i++){
23             if((array[i] & (1 << index))!=0){
24                 num2[0] ^= array[i];
25             }else{
26                 num1[0] ^= array[i];
27             }
28         }
29     }
30 /**
31      * 數組a中只有一個數出現一次,其餘數都出現了2次,找出這個數字
32      * @param a
33      * @return
34      */
35     public static int find1From2(int[] a){
36         int len = a.length, res = 0;
37         for(int i = 0; i < len; i++){
38             res = res ^ a[i];
39         }
40         return res;
41     }
View Code
相關文章
相關標籤/搜索