奇妙的位运算
三道leetcode上的題目。
Single Number
Given an array of integers, every element appears?twice?except for one. Find that single one.
題意即:一個數組,里面的元素每個都出現了兩次,除了一個特殊的,求這個特殊元素。接觸過這類題目的coder很快能夠脫口而出:直接異或就ok了!因為兩個相同的數異或會抵消每個bit位,結果為0.
1 class Solution { 2 public: 3 int singleNumber(vector<int>& nums) { 4 int x=0,len=nums.size(); 5 for(int i=0;i<len;i++) x^=nums[i]; 6 return x; 7 } 8 };Single Number II
Given an array of integers, every element appears?three?times except for one. Find that single one.
題意:這是上題的加強版,數組中每個元素都出現三次,除了一個特殊的,找出這個特殊元素。
思路:我們也可以按位運算,計算1 bit的數量,如果每個數字都出現三次,那么每位上的1 bit數量肯定是3的倍數,相反如果不是3的倍數,那么就是那個特殊的數。但是我們可以用一個數“輔助”,因為每一位的1 bit數量統計都是類似的,所以假設正在統計某一位的1 bit數量。我們用a來表示 1 bit 的數量,當 1 bit 的數量為0時,a=0;當數量為1時,a=1;當數量為2時,a=2?非也,位運算只能表示0和1,所以這時我們引進第二個變量b,我們用b=1來代表已經有了2個 1 bit,所以當有兩個 1 bit 時,a=0,b=1。數量統計結果逢3化0,所以只有0、1、2三種結果:
bits數量 a b0 0 01 1 02 0 1思路也就顯而易見了,每次運算我們維護a和b的值,運算到最后即可得到結果:
1 class Solution { 2 public: 3 int singleNumber(vector<int>& nums) { 4 int a=0,b=0,len=nums.size(); 5 for(int i=0;i<len;i++){ 6 b=a&(b^nums[i]);//b由a和b異或item的對應bit與決定 7 a=b|(a^nums[i]);//a由b和a異或item的對應bit或決定 8 } 9 return a; 10 } 11 };Single Number III
Given an array of numbers?nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given?nums = [1, 2, 1, 3, 2, 5], return?[3, 5].
題意:還是一個數組,每個元素出現兩次,只有兩個特殊的元素出現一次,把這兩個特殊的元素找出來。
思路:直接異或不得行。考慮兩個特殊值,他們肯定有bit不同,想辦法分開他們,再分別與其他數異或,就出來了。把所有數異或(效果等同于把兩特殊數異或),取結果某個bit上的1,根據此位把數組分為兩個子數組,則目的達到。
1 class Solution { 2 public: 3 vector<int> singleNumber(vector<int>& nums) { 4 int x=0,len=nums.size(); 5 for(int i=0;i<len;i++) x^=nums[i]; 6 x=x&(-x);//取x最右邊為1的bit位 7 int r1=0,r2=0; 8 for(int i=0;i<len;i++) (nums[i]&x)?(r1^=nums[i]):(r2^=nums[i]); 9 vector<int> t; 10 t.push_back(r1); 11 t.push_back(r2); 12 return t; 13 } 14 };?
參考:http://www.cnblogs.com/zichi/p/4795049.html
轉載于:https://www.cnblogs.com/jiu0821/p/4677184.html
總結