LeetCode修仙:Two Sum详解

不重要:

最近天天玩吃鸡,优点颓废,好好坚持刷一下LeetCode,本博客力求一题多解,从时间复杂度上完成自我代码修养的提高。

problem:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].


方法1:

分析:

首先我们知道:无需把数组中所有的符合要求的下标组列出来,只需要一组,并且与顺序无关。我们很容易想到一种思路如下图:


我们可以从第一个蓝色开始:一个一个跟后面的比对;继而黄色;以此类推...发现有数据对满足和为:target.就结束寻找;并返回两者下标;


代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
      vector<int> answer;
      int len=(int)nums.size();
      for(int i=0;i<len-1;i++)  
          for(int j=i+1;j<len;j++) 
          {
              if((nums[i]+nums[j])==target)
              { 
                  answer.insert(answer.end(), i);
                  answer.insert(answer.end(), j);
                  break;
              }
          }
       return answer;
    }
};

运行效果:


可能错误:

reference binding to null pointer of type 'value_type'
注意:vector的赋值分两个,一者在初始化的时候;一者在后续插入。由于代码中answer的初始化未进行,所以,如果用

                  answer[0]=i;
                  answer[1]=j;

替换

                  answer.insert(answer.end(), i);
                  answer.insert(answer.end(), j);

则会出现上述错误;


方法2:

上述的方法虽然可以通过,但是我们不难发现,时间成本还是比较高,时间复杂度是O(N^2),显然不是最优秀的解法,于是,上网搜索更好的思路发现了新大陆:hash_map,通过这种Key+value的快速搜索结构体,我们可以进一步加快我们的程序;

新版的C++ 11中hash_map都是unordered_map了,所以这里只说unordered_map,但也要区分它和map的区别:

运行效率方面:unordered_map最高,而map效率较低但 提供了稳定效率和有序的序列。

占用内存方面:map内存占用略低,unordered_map内存占用略高,而且是线性成比例的。


unordered_map的用法:


开头:

     #include<tr1/unordered_map>//加上tr1库名,
     using namespace std::tr1;//加上命名空间


初始化:

unorder_map<int, string> mapStudent;  
mapStudent[1] =  “student_one”;
mapStudent[2] =  “student_two”;
mapStudent[3] =  “student_three”;

查找:
    若有unordered_map<int, int> mp;查找x是否在map中
    方法1:  若存在  mp.find(x)!=mp.end()
    方法2:  若存在  mp.count(x)!=0

插入:

map.insert(map::value_type(1,"Raoul"));


遍历:

       unordered_map<int, string>::iterator  iter;map<int, string>::iterator  iter;
       for(iter = mapStudent.begin();  iter != mapStudent.end();  iter++)

         {...}


利用Value查找Key&&删除:

       map<int, string>::iterator iter;

       iter = mapStudent.find(1);

       mapStudent.erase(iter);


代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
      vector<int> answer;
      unordered_map<int,int> hash;
      for(int i=0; i<nums.size(); i++)
      {
          int NumToFind=target-nums[i];
          if(hash.find(NumToFind) != hash.end())
          {
              answer.push_back(hash[NumToFind]);
              answer.push_back(i);
              return answer;
              break;
          }
          else
              hash[nums[i]]=i;
      }
    }
};


代码注解:

你可能觉得hash对象并没有被初始化:这不是问题:因为这里比较巧妙,hash一开始确实是空的:不过在每一次循环中,最后都会执行:

hash[nums[i]]=i;
所以hash是从头部开始进入的:比如:【2,6,9,8,3,4】target=5
最后输出的是第五层for循环中(i=4),发现NumToFind=5-3=2时候,从hash中找到了2,这样得出来的,这也解释了answer中为什么先push进去的不是i;所以这里有点巧妙,也可以说:有点难理解,是一个“反哺”的机制,挺有意思的;


运行结果:


总结:

这样,时间从189ms提高到了9ms,十分满足,而且也顺便学了unordered_map的用法。




猜你喜欢

转载自blog.csdn.net/Errors_In_Life/article/details/79058378