演算法題 只出現一次的數字Ⅰ/Ⅱ/Ⅲ
阿新 • • 發佈:2018-12-26
136. 只出現一次的數字
給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。
思路:本來使用HashMap做,後來才知道這是位運算方面的題,慚愧。
由於其他元素都出現了兩次,因此把全部元素亦或一下,結果就出來了。。
class Solution { public static int singleNumber(int[] nums) { int result=0; for(int i=0;i<nums.length;i++){ result^=nums[i]; } return result; } }
137. 只出現一次的數字 II
給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。
思路:其他元素都出現了三次,按位計算每一位上1的個數,結果模3為1的那些位就是所求數二進位制1所在的位。
class Solution { public static int singleNumber(int[] nums) { int result = 0; for(int i=0;i<32;i++){ int mask = 1<<i; int count = 0; for(int j=0;j<nums.length;j++){ if((mask&nums[j])!=0) count++; } if(count%3==1) result = mask|result; } return result; } }
260. 只出現一次的數字 III
給定一個整數陣列 nums
,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。
思路:
原話:
這道題主要和Ⅰ類似,但是這裡有兩個不同的數,所以需要從這兩個數的異或值反推得到結果。整數的二進位制在java中是補碼錶示,所以我們可以用n&-n得到n的二進位制最右邊的一個1。這樣對於這個為1的位置,肯定可以分辨出這兩個數,因為一定有兩個數在這個位置1個為1,另一個為0。所以遍歷整個陣列,和這個數做&操作,就可以將兩個數分開到兩組中。因為其他出現兩次的數,異或操作還是為0,對結果沒有影響,所以對每個遍歷到的數做異或操作即可。
理解:
還是先將全部數亦或一下,得到的結果n就是我們要的兩個數亦或的結果。然後反推這兩個數。n&-n(不好理解的話可以換為n & ~(n-1)理解)得到兩個數不同的最低位。接著將全部數分成兩個組,一組為該位上是0的,另一組為該位上是1的。把兩組分別組內亦或,就可以得到我們要的兩個數。
class Solution {
public int[] singleNumber(int[] nums) {
int sum = 0; //記錄所有異或的值,即兩個只出現一次數的異或
for(int i=0;i<nums.length;i++){
sum ^= nums[i];
}
int[] res = new int[2];
sum &= -sum; //得出兩個數異或結果的最右邊的一個1,其他的為零,這樣進行&操作就可以將兩個不同的數分到不同的兩組去
for(int i=0;i<nums.length;i++){
if((sum&nums[i])==0)
res[0] ^= nums[i];
else
res[1]^=nums[i];
}
return res;
}
}
https://www.cnblogs.com/271934Liao/p/7158888.html