1. 程式人生 > >LeetCode Two Sum 及C++map淺顯理解

LeetCode Two Sum 及C++map淺顯理解

今天正式開始刷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。