leetcode single numbers I II III

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

题解:可以利用^ 操作符,按位 异或 。 规则: 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 bit
	so 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值