leetcode136题解

来源:互联网 发布:淘宝代销怎么没有了 编辑:程序博客网 时间:2024/05/21 13:53

leetcode 136.Single Number

题目

Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
翻译过来就是,一堆数字里面,除了一个元素只出现一次外,其余都出现了两次。找出那个只出现一次的。
例如,【2,2,1】 程序输出结果应为1.

解题思路

光看题目的话,这道题很简单。稍微想想大概就有4种算法:
1. 双重循环。
这是最容易想到的,一个一个数比较就行。此处不给出具体代码,但需要注意的是这种算法的时间复杂度为O(n^2),并不能AC,会超过时间限制。

  1. 用一个数组标记某个元素是否出现过。
    我刚看到题目时就是这个思路,因为之前做过一道类似的题目——找寻只出现一次的ASCII码。但在做这道题时我发现好像行不通,ASCII码可以通过一个bool【256】的数组来标记,在本题中因为输入的数字大小不确定,所以没法建立一个合适大小的数组,用new的话可能又比较浪费空间。所以这种想法GG。

  2. 稍稍改变一下思路,排序+比较相邻元素 好像行得通的样子。
    具体思路就是:先对输入数组排序,然后比较相邻元素,步长为2.这里要介绍一下STL里的sort排序函数,用的是快速排序,时间复杂度为O(nlogn)。不用自己写排序算法,程序就非常简单了。
    详见AC代码思路3

  3. 使用STL中的set
    unordered_set是C++11中刚刚加入的,它基于哈希表,一个存储唯一(Unique,即无重复)元素的关联容器,容器中的元素无特别的次序关系。该容器允许基于值地快速元素检索。这里不做具体介绍,这里用它是因为其检索十分快速,我们可以用find函数很快寻找是否有相同元素,然后再做删除或插入操作即可。
    详见AC代码思路4

  4. 用异或,从位操作的角度考虑。
    可以看到leetcode里面要求的时间复杂度前几种算法已经满足了,但上述几种算法都需要额外的数据储存空间。而leetcode要求的是不使用额外的存储空间,这个我想了半天也没有想法。后来参考的leetcode上的大神代码才恍然大悟。嗯,和大神差距还是非常非常大的。
    算法很简单,就是用异或运算符。说几个很容易证明的结论,A^0=A,A^A=0.即A与0的异或是其自身,而两个相同数字的异或结果为0.知道了这个,算法也就很容易了,将数组逐个异或,结果就是只出现过一次的值。
    详见AC代码思路5

AC代码如下

思路3:

//时间32msclass Solution { public:int singleNumber(vector<int>& nums) {      sort(nums.begin(),nums.end());       int index=0;       while(index<nums.size()-1){        if(nums[index]==nums[index+1])            index+=2;        else            return nums[index];       }return nums[index];}};

思路4:

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

思路5:

//13msclass Solution {public:int singleNumber(vector<int>& nums) {   int result=0;   for(int i=0;i<nums.size();i++){     result^=nums[i];   }   return result;}};

总结

这道题在leetcode上是easy难度,但要完全实现时间复杂度线性,无需额外空间,如果没有考虑到位操作,很难实现。
我们现在来看看每个思路运行的时间,可以看到排序+比较 最慢,可能是因为排序耗费了较多时间;用unordered_set的运行时间提高了不少,可以看到选择合适的数据结构很重要;最后的异或算法自然是运行时间最短,另外不需要额外空间。如果面试官限制了不允许使用STL及内置函数,那这道题异或算法无疑是面试官最想听到的答案。
最后总结一下,遇到这种可能有大量数据、空间复杂度要求特别严苛,普通数据结构或算法没法达到的,就可以考虑考虑位操作了。对bit的操作,一般来说,时间复杂度和空间复杂度都十分优秀。

最后一些话

今天收到了摩根IT暑期实习的拒信,有点伤心,自己确实能力不够,知识积累也不多,好像也没啥可抱怨的。Talk is cheap,show your code. 慢慢积累,慢慢进步。与诸君一起进步!

原创粉丝点击