码迷,mamicode.com
首页 > 其他好文 > 详细

Single Number | & || & |||

时间:2016-07-04 13:24:00      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

Single Number

Given 2*n + 1 numbers, every numbers occurs twice except one, find it.

Example

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 }

Single Number II

Given 3*n + 1 numbers, every numbers occurs triple times except one, find it.

Example

Given [1,1,2,3,3,3,2,2,4,1] return 4

由于x^x^x = x,无法直接利用I的方法来解。但可以应用类似的思路,即利用位运算来消除重复3次的数。以一个数组[14 14 14 9]为例,将每个数字以二进制表达:
 
1110
1110
1110
1001
_____
4331    对每一位进行求和
1001    对每一位的和做%3运算,来消去所有重复3次的数
 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 }

Single Number III

Given 2*n + 2 numbers, every numbers occurs twice except two, find them.

Example

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

Single Number | & || & |||

标签:

原文地址:http://www.cnblogs.com/beiyeqingteng/p/5639938.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!