zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    CCNA 第二章 以太网回顾
    CCNA 第一章 网络互联
    solidworks中 toolbox调用出现未配置的解决方法
    linux之df命令
    linux之du命令
    linux之pid文件
    linux之mysql启动问题
    linux之使用cron,logrotate管理日志文件
    wordpress(一)wordpress环境的搭建
    phpwind8.7升级9.0.1过程(四)20130207升级到20141228
  • 原文地址:https://www.cnblogs.com/ketchups-notes/p/4476571.html
Copyright © 2011-2022 走看看