LeetCode Two Sum 及C++map浅显理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Murdock_C/article/details/49851547

今天正式开始刷LeetCode,发现上面和其它地方的oj真的不太一样。首先,最最最好的一点就是你可以在上面在线敲代码然后运行,不用自己再打开vs或者dev,然后就是,它不让你关心数据到底是如何输入输出的,唯一关心的就是你的核心代码,就是说只要主体结构正确,你不用考虑输入输出(这个简直太良心了,其它OJ好多题都是死在输入输出上有木有!),完成solution这个函数(或者类,在C++下)就行。
好了,我们来看下第一道题,Two Sum,意思是给你一个整型的数组,让你找出其中两个数加起来可以相等于target的数的下标。第一眼看到这个题的时候,就想,这还不简单,不就两个for循环吗,简单

for (int i=0; i<numbers.size(); ++i)
{
    for (int j=i+1; j<numbers.size(); ++j)
    {
        if (numbers[i] + numbers[j] == target)
        {
            a = i;
            b = j;
            break;
        }
    }
}

然后,就TLE了,说明不能这么简单的去做。后来又试了另外一种做法,就是新建个类,类中保存数组的值及对应的下标位置,然后对这些类组成的vector进行从小到大排序,额,还是看代码吧

class Node{
  public:
    int value;//用来保存数组的值
    int key;  //用来保存对应值所对应的下标
};

bool cmp(Node a, Node b)
{
    return a.value < b.value; //排序函数所需谓词,从小到大进行排序
}
class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        int i, sum;
        vector<int> results;             //用来保存结果
        vector<Node> arry;               
        for (i=0; i<numbers.size(); ++i) //这一步就是将数组numbers所有的值及相对应的下标存进去
        {
            Node *tmp = new Node;
            tmp->value = numbers[i];
            tmp->key = i+1;
            arry.push_back(*tmp);
        }
        sort(arry.begin(),arry.end(),cmp); //对arry按照值的大小从小到大进行排序

        vector<Node>::iterator j = arry.begin();
        vector<Node>::iterator k = arry.end()-1;
        sum = 0;
        /*
        这一部分很简单,其实就是对已经排序好的arry从两头开始
        进行查找,若sum小于target,很明显需要将j往后移位,若sum
        大于target,很明显需要将k往前移位,直到找到sum==target
        */
        while (j < k)                 
        {                             
            sum = j->value + k->value;
            if (sum > target) --k;    
            else if (sum < target) ++j;
            else
            {
                int temp;
                if (j->key > k->key)//考虑到数组中有负数的原因,会因为排序后而发生j->key > k->key 的现象,需要调换
                {
                    temp = j->key;
                    j->key = k->key;
                    k->key = temp;
                }
                results.push_back(j->key);
                results.push_back(k->key);
                break;
            }
        }

        return results;
    }
};

这个过了,时间复杂度最大也就sort函数吧,大概O(nlgn),比O(n2)好多了。
还有看见discuss里面有大神用c++的map来做,确实简单多了,贴代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        int i, sum;
        vector<int> results;
        map<int, int> hmap;
        for(i=0; i<numbers.size(); i++){
            if(!hmap.count(numbers[i])){
                hmap.insert(pair<int, int>(numbers[i], i));
            }
            if(hmap.count(target-numbers[i])){
                int n=hmap[target-numbers[i]];
                if(n<i){
                    results.push_back(n+1);
                    results.push_back(i+1);

                    return results;
                }

            }
        }
        return results;
    }
};

map是c++里面的一种关联容器,其原型是map

if(!hmap.count(numbers[i])){
                hmap.insert(pair<int, int>(numbers[i], i));
            }

意思就是如果numbers[i]在map中没有出现过,就将(numbers[i],i)插入到map中,其中numbers[i]相当于key,i相当于value。因为map中的查找是很快的,所以时间复杂度很低。
另外,map要求其中的key值不允许重复,即一个key只对应一个value。

猜你喜欢

转载自blog.csdn.net/Murdock_C/article/details/49851547