<LeetCode OJ> 136 / 137 / 260 Single Number(I / II / III)

136题目:

给定一个整数数组,每个元素会出现两次,但是除了一个。找到这个数。


分析:

直接通过哈希查找是否出现过,如果没有出现过就压入哈希,如果出现过就删除哈希中的元素,这样做最终会留下只出现一次的元素。44ms

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_set<int> hashset;  
        for(int i=0;i<nums.size();i++)  
        {  
            //if(hashset.count(num[i]))//count统计是否出现过(然而对于hashset,这样更慢一些)  
            if (hashset.find(nums[i]) != hashset.end())//直接查找,哈希查找常数时间复杂度     
                hashset.erase(nums[i]);  
            else  
                hashset.insert(nums[i]);  
        }  
        unordered_set<int>::iterator p=hashset.begin();  
        return *p;  
    }
};



(参考于讨论区)正确的做法

第二种方法,位运算:

异或,异则真,同则假。XOR (^)
异或的性质1:交换律a ^ b = b ^ a,性质2:0 ^ a = a。
所有元素异或,最终结果就是出现一次的数 

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int value = 0;
        for(int i=0; i<nums.size(); i++)
            value = value ^ nums[i];//所有元素异或,最终结果就是出现一次的数  
        return value;
    }
};





137. Single Number II

Total Accepted: 70740  Total Submissions: 194635  Difficulty: Medium

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?




我的解法(没有符合题目要求),28ms

class Solution {
public:
	int singleNumber(vector<int>& nums) {
		unordered_multiset<int> hashset;//允许重复关键值出现
		for (int i = 0; i<nums.size(); i++)
		{
			if (hashset.count(nums[i]) == 2)//count统计是否出现过(然而对于hashset,这样更慢一些)      
			   hashset.erase(nums[i]);
			else
			   hashset.insert(nums[i]);
		}
		unordered_multiset<int>::iterator p = hashset.begin();
		return *p;
	}
};



别人家的解法:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int a=0;
        int b=0;
        for(int c:nums){
            int ta=(~a&b&c)|(a&~b&~c);
            b=(~a&~b&c)|(~a&b&~c);
            a=ta;
        }
        //we need find the number that is 01,10 => 1, 00 => 0.
        return a|b;
    }
};



260. Single Number III

Total Accepted: 19802  Total Submissions: 47891  Difficulty: Medium

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].

Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?




第一种方法:set方法(红黑树),68ms

思路首先:利用set来做,如果nums[i]在set中就不插入到set并且删除该值
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        set<int> s;
        vector<int> num=nums;
        for(int i=0;i<num.size();i++)
        {
            //if(s.count(num[i]))//count统计是否出现过(更快一些)
            if (s.find(num[i]) != s.end())//直接查找,红黑树查找很快   
                s.erase(num[i]);
            else
                s.insert(num[i]);
        }
        vector<int> ans(2,0);
        set<int>::iterator p;
        int i=0;
        for(p = s.begin();p != s.end();p++,i++)
            ans[i]=*p; //set是无序容器,不能像数组那样s[i]这样的操作
        return ans;
    }
};


第二种方法:哈希方法,32ms

//思路首先:利用unordered_set来做,如果nums[i]在unordered_set中就不插入到unordered_set并且删除该值
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        unordered_set<int> hashset;
        vector<int> num=nums;
        for(int i=0;i<num.size();i++)
        {
            //if(hashset.count(num[i]))//count统计是否出现过(然而对于hashset,这样更慢一些)
            if (hashset.find(num[i]) != hashset.end())//直接查找,红黑树查找很快   
                hashset.erase(num[i]);
            else
                hashset.insert(num[i]);
        }
        vector<int> ans(2,0);
        unordered_set<int>::iterator p;
        int i=0;
        for(p = hashset.begin();p != hashset.end();p++,i++)
            ans[i]=*p; //set是无序容器,不能像数组那样s[i]这样的操作
        return ans;
    }
};



注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50445175

原作者博客:http://blog.csdn.net/ebowtang

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值