OJ练习40——T1 Two Sum

练习1-39是简单题目,练习40开始做中级题目。

找到一个序列中的两个序号,要求该序号对应的两个数和为指定值。

【思路】

1.暴力解决:大循环遍历作为左数,小循环从下一个开始遍历作为右数,时间复杂度是O(n^2)。——竟然不让我通过%>_<%

2.哈希散列,用map<int, int>实现,序号(左值)是原序列中的值,保存的值(右值)是原序列的序号,每次从map中遍历。每次查找当前(target-当前值)是否已在表中,

若已存在,则返回key对应的序号和当前序号,否则添加当前值到表中。

3.别人的办法:用unordered_map类,思路和2一样。

        ——2、3的思路:遍历原序列的值,而不是原序列的索引,可以减少一个级的复杂度(n^2到n),hashtable中查找元素时间为常数的优势。

4.c的思路:先排序,然后用快排思想,一个在头一个在尾,比较头尾两数的和与指定值的大小。或者先快排至有序,然后二分查找。时间是O(nlogn).

【思路2+3 other code】注意:使用map要#include<map>

vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result(2);
        map<int,int> intMap;//思路2
//unordered_map<int,int> intMap;//思路3
for(int i=0; i<nums.size(); ++i){ if(intMap.find(target-nums[i]) != intMap.end()){ result[0] = intMap[target-nums[i]] + 1; result[1] = i + 1; return result; } intMap[nums[i]] = i; } }

【结果】

用思路3的unordered_map耗时20ms,排名居中;

用思路2的map耗时39ms,排名最后,可见散列表的效率要更高些,

因为map底层使用红黑树实现的,所以它的查找时间是O(logN),略逊于hash_map,但是这不是绝对的。

(see more:http://blog.csdn.net/jiadebin890724/article/details/23305449)

find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。

这个“键值”就是指“序号”,如果直接引用intMap[key],key是一个未曾出现过的键,那么映射表会自动创建一个具有这个键的新元素,即intMap[nums[i]] = i;

【思路4】

vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        int n=nums.size();
        sort(nums.begin(), nums.end());
        int i=0,j=n-1;
        while(i<j){
            if(nums[i]+nums[j]==target){
                result.push_back(i+1);
                result.push_back(j+1);
                return result;
            }
            else if(nums[i]+nums[j]<target){
                i++;
            }
            else if(nums[i]+nums[j]>target){
                j--;
            }
        }
    }

排序用stl提供的sort函数很好实现,但是修改了原来元素的顺序,返回的是排序后的序号,是不符合题意的。可以间接实现:

struct Node
{
    int data;
    int num;
};
bool comparision(Node n1, Node n2)
{
    return n1.data<n2.data;
}
vector<int> twosum(vector<int> &nums, int integer)
{
    int first, second;
    const int length=nums.size();
    vector<Node> nodes(length);
    vector<int> re;
    for(int i=0; i<length; i++)
    {
        nodes[i].data=nums[i];
        nodes[i].num=i;
    }
    sort(nodes.begin(), nodes.end(),comparision);
    for(int i=0,j=length-1; i!=j;)
    {
        int sum=nodes[i].data+nodes[j].data;
        if(sum==integer)
        {
            if(nodes[i].num<nodes[j].num){
                re.push_back(nodes[i].num);
                re.push_back(nodes[j].num);
            }
            else{
                re.push_back(nodes[j].num);
                re.push_back(nodes[i].num);
            }
            return re;
        }
        else if(sum<integer)
            i++;
        else
            j--;
    }    
}

利用自定义结构体,把序号和值捆绑。其实相当于map。

还有更优美的写法,见http://blog.csdn.net/sunbaigui/article/details/8981343

原文地址:https://www.cnblogs.com/ketchups-notes/p/4476571.html