leetcode single numbers I II III

来源:互联网 发布:免费淘宝网店模板 编辑:程序博客网 时间:2024/06/05 09:16

题意:给一个数组,其中每个数都出现两次,只有一个数出现一次,请求出这个数。

题解:可以利用^ 操作符,按位 异或 。 规则: X^X=0,X^0=X;那么所有出现两次的数 抑或后 结果为0 ,再与出现一次的数异或,得到的就是结果

代码:

方法一:

int singleNumber(vector<int>& nums) {        int n = nums.size(), i = 0, ret = 0;        for (i = 0; i < n; ++i)            ret ^= nums[i];        return ret;    }

方法二:

vector<int> singleNumber(vector<int>& nums) {unordered_set<int> mySet;for (int i = 0; i<nums.size(); i++){if (mySet.find(nums[i]) == mySet.end()) mySet.insert(nums[i]);else mySet.erase(nums[i]);}auto it = mySet.begin();vector<int> vec;vec.push_back(*it);return vec;}

方法三:

int singleNumber(vector<int>& nums) {        sort(nums.begin(),nums.end());        for(int i=1;i<nums.size();i+=2){            if(i!=nums.size()&&nums[i]!=nums[i-1]){                return nums[i-1];            }        }        return nums[nums.size()-1];    }




升级:给一个数组,其中每个数都出现两次,有两个数出现一次,请求出这两个数。

题解:可以使用哈希set,即unordered_set<int> mySet   ,当每插入一个元素时,检查集合里是否出现过,如果出现过,就将这个数擦除,否则就添加进去,最后集合里的两个元素就是 答案。当然,上题也可以用这个方法做。

代码:

class Solution {public:    vector<int> singleNumber(vector<int>& nums) {        unordered_set<int> mySet;        for(int i=0;i<nums.size();i++){            if(mySet.find(nums[i])==mySet.end()) mySet.insert(nums[i]);            else mySet.erase(nums[i]);        }        auto it=mySet.begin();        vector<int> vec;        vec.push_back(*it);        it++;        vec.push_back(*it);        return vec;    }};

方法二:

可以利用^ 操作符,按位 异或 。 规则: X^X=0,X^0=X;那么 假设输入为1,2,1,2,3,4. n=7,对应二进制位0111,1^2^1^2^3^4实际上等于3^4,现在也就是需要区分3和4.

假设用a和b分别存不同的这两位,我们知道a和b不同,那么其对应的二进制必然有一位不一样,所以a^b=n,必然就不为0,那么就必然有一位为1。那么我们就找出来这一位来区分a和b,用这一位来讲输入的array分为两组。 这里我们用flag来区分,flag表示n的最后一位'1',flag=n&(~(n-1)),  其中n&(~n)=0,而n&(~(n-1))就表示最右边一位’1‘,其余位均为0。再用flag来和其余所有的数按位&,nums[i]中这一位为1的为一组,这一位为0的为另一组。这样后,就分为了两组,就回归到了第一题中的方法一。代码如下:


vector<int> singleNumber(vector<int>& nums) {int n = 0;vector<int> res;for (int i = 0; i < nums.size(); i++) {n = n ^ nums[i];}/*flag is the last "1" bit of n,the two elements which appear only once must be defferent in this bitso we can use flag to devide all the elements into two parts,one contains a and the other one contains b.*/int flag = n & (~(n - 1));int a = 0, b = 0;for (int i = 0; i < nums.size(); i++) {if ((flag&nums[i]) == 0) a ^= nums[i];else b ^= nums[i];}res.push_back(a);res.push_back(b);return res;}


方法三:用排序的思想

vector<int> singleNumber03(vector<int>& nums){sort(nums.begin(),nums.end());int i = 0;vector<int> vec;while (i < nums.size()-1){if (nums[i] != nums[i + 1]){vec.push_back(nums[i]);i++;}else{i += 2;}}if (i == nums.size() - 1) vec.push_back(nums[i]);return vec;}

再升级,一个Array,其中每个数都出现3次,只有一个数仅出现1次,找出这个数。

题解:之前的都是出现偶数次,仅仅用按位异或便可求得,但是出现奇数次该怎么做,同样是用位运算。 假如每个数都出现3次,没有出现1次2次的,那么对应的二进制每个位上的和应该能被3整除,这个时候来一个仅仅出现1次的,那么该位模除3得到的1便是 那个出现1次的数在该位的值。

那么就有一个通用的解法。记录每个位的状态,最后返回。

class Solution {public:    int singleNumber(vector<int>& nums) {       int bits[32]={0};       int ret=0;       for(int i=0;i<32;i++){           for(int j=0;j<nums.size();j++){               bits[i]+=(nums[j]>>i)&1;           }           ret|=bits[i]%3<<i;       }       return ret;    }};



0 0
原创粉丝点击