标签:
Given 2*n + 1
numbers, every numbers occurs twice except one, find it.
Given [1,2,2,1,3,4,3]
, return 4
分析:
利用bit operator ^ 的特点即可。
1 public class Solution { 2 /** 3 *@param A : an integer array 4 *return : a integer 5 */ 6 public int singleNumber(int[] A) { 7 if (A.length == 0) return 0; 8 9 int n = A[0]; 10 for(int i = 1; i < A.length; i++) { 11 n = n ^ A[i]; 12 } 13 return n; 14 } 15 }
Given 3*n + 1
numbers, every numbers occurs triple times except one, find it.
Given [1,1,2,3,3,3,2,2,4,1]
return 4
1 public class Solution { 2 /** 3 * @param A : An integer array 4 * @return : An integer 5 */ 6 public int singleNumberII(int[] A) { 7 int[] count = new int[32]; 8 int result = 0; 9 for (int i = 0; i < 32; i++) { 10 for (int j = 0; j < A.length; j++) { 11 if (((A[j] >> i) & 1) == 1) { 12 count[i]++; 13 } 14 } 15 result = result | ((count[i] % 3) << i); 16 } 17 return result; 18 } 19 }
Given 2*n + 2
numbers, every numbers occurs twice except two, find them.
Given [1,2,2,3,4,4,5,3]
return 1
and 5.
分析:
很容易联想到 I 的解法,把所有数异或起来。但是异或之后我们得到的是我们想要的那两个数的异或值,如何把它们从异或中拆分开呢?
假设我们要找的这两个数为 a, b, 而 x = a ^ b。
首先,a 肯定不等于 b,那么说明它们的二进制位一定是不完全相同的,所以 x 肯定不为 0。
也就是说,a 与 b 一定存在“某一位”,使得在它们中的某个数中是 0,而在另一个数中是 1,这是他们之间的一个差别。
我们可不可以利用这个差别来把这两个数从 x 中揪出来呢? 是可以的。
利用这个差别,我们可以将整个 nums 集合分成两个集合。一个集合中是这 “某一位” 为 0 的在nums中的所有数,假设为集合 A。而另一个集合是这 “某一位” 为 1 的在nums中的所有数。假设 a 的这 “某一位” 是 0 ,b 的 这个“某一位”是1,那么显然 a 在集合 A 中,b 在集合 B 中,这样问题就完全转化成了与 I 一样的两个子问题,于是可以得解。
关于具体的代码实现,还有一点说明:
我们如何找到这个 “某一位” 呢?理论上,只要是在这一位上 a与b的值不同,都可以合格的成为我们需要找的某一位。既然无更多限制,那我们肯定是找好找的某一位咯。
我们可以用很常规和易懂的方法去找,但一般而言,我们肯定是找最右边(低位)那边符合要求的“某一位”嘛。更进一步说,就是找到 x 中最低位的 1 嘛。那当然我们可以从最低位开始枚举每一位,直到找到我们需要找的那个“某一位”。
还有一种更trick利用位运算的办法:找到 x 中最低位的 1,仔细想想,这跟另外一个已经熟知的问题很像。
当我们统计某个数的二进制展开中1的个数的时候,我们使用了一个技巧,即用 n &= n - 1 每次来清除 n 中当前最右边的那个 1。
n-1 是把 n 的最低位的 1 变成 0,并且使更低位的 0 全部变成 1,然后异或一下就把 最低位的 1 及其更低位全部都变成了 0,即达到了“清除最低位的 1 的目的”。
1 public class Solution { 2 /** 3 * @param A : An integer array 4 * @return : Two integers 5 */ 6 public List<Integer> singleNumberIII(int[] A) { 7 ArrayList<Integer> nums = new ArrayList<Integer>(); 8 if (A == null || A.length == 0) return nums; 9 10 int xorResult = 0; 11 for (int i : A) { 12 xorResult ^= i; 13 } 14 15 // get the last 1 bit of x1xorx2, e.g. 1010 ==> 0010 16 int last1Bit = xorResult - (xorResult & (xorResult - 1)); 17 int single1 = 0, single2 = 0; 18 for (int i : A) { 19 if ((last1Bit & i) == 0) { 20 single1 ^= i; 21 } else { 22 single2 ^= i; 23 } 24 } 25 26 nums.add(single1); 27 nums.add(single2); 28 return nums; 29 } 30 }
Reference:
http://bangbingsyb.blogspot.com/2014/11/leetcode-single-number-i-ii.html
http://www.cnblogs.com/maples7/p/4483196.html
标签:
原文地址:http://www.cnblogs.com/beiyeqingteng/p/5639938.html