• Leetcode 1 Two Sum


    1.题目要求

    Given an array of integers, find two numbers such that they add up to a specific target number.

    The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

    You may assume that each input would have exactly one solution.

    Input: numbers={2, 7, 11, 15}, target=9
    Output: index1=1, index2=2

    2.分析

    读完题,第一个想法就是两层循环遍历,这个算法最直接,最容易想到,因此时间复杂度也是最高的O(n*n)。

    class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            vector<int> myVector;
            myVector.clear();
            
            int sizeOfNum = numbers.size();
            bool flag=true;
            for (int i=0;flag&&i<sizeOfNum;i++)
            {
                for (int j=i+1;j<sizeOfNum;j++)
                {
                    if(target == numbers[i]+numbers[j])
                    {
                        flag=false;
                        myVector.push_back(i+1);
                        myVector.push_back(j+1);
                        break;
                    }
                }
            }
            return myVector;
    
        }
    };

    最终提交肯定也不会Accepted。因此需要改进算法,降低时间复杂度。

    在算法世界,常见的时间复杂度是O(n*n),O(n*lgn),O(n),O(lgn),因此,我们猜想可不可以把时间复杂度降到O(n*lgn),一看到这个时间复杂度,就应该想到排序算法的时间复杂度,也是O(n*lgn),为了保证数的原始下标不被修改,需要将下标随数据一起改变位置。因此,我们可以先将数排序,然后在查找是否有符合条件的数据。

    struct data 
    {
        int num;
        int index;
        bool operator<(const data &right)
        {
            return (*this).num < right.num;
        }
    };
    
    class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            vector<data> myVector;
            data temp;
            vector<int> result;
            myVector.clear();
            int sizeOfNum = numbers.size();
            bool flag=true;
            int i,j,middle;
            for (i=0;i<sizeOfNum;i++)
            {
                temp.num = numbers[i];
                temp.index = i;
                myVector.push_back(temp);
            }
            sort(myVector.begin(),myVector.end());
            for (i=0,j=sizeOfNum-1;i<=j;)
            {
                middle= myVector[i].num + myVector[j].num;
    
                if(target == middle)
                    break;
                else if(target > middle)
                {
                    i++;
                }else
                    j--;
            }
            //cout << myVector[i].index+1 << " " << myVector[j].index+1<<endl;
            if (myVector[i].index<myVector[j].index)
            {
                result.push_back(myVector[i].index+1);    
                result.push_back(myVector[j].index+1);
            }else
            {
                result.push_back(myVector[j].index+1);    
                result.push_back(myVector[i].index+1);
    
            }
    
    
            return result;
    
        }
        
    };

    呵呵,Accepted。所以这个算法是可行。

    虽然问题已经解决了,但我们还可以精益求精啊,想想还有没有更好的算法,那就要考虑能不能在O(n)的时间复杂度内完成这个题目。

    如果时间复杂度是O(n),那意味着只需要遍历这个序列就能找出符合条件的数据,在此基础上考虑怎样实现。

    遍历序列就能确定符合条件的数据的下标,则需要保存好数据和下标之间的映射,因此可以考虑用map结构保存二者之间的映射关系,有了这种映射关系,接下来就是考虑怎样将满足条件的数据变换到同一个map元素;比如题目中:四个pair:<2,1>,<7,2>,<11,3>,<15,4>,依次遍历每一个pair,并且需要在map中以key=target-number[i]进行查找,如果找到,则有符合条件的数据。

    class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            vector<int> result;
            result.clear();
            map<int,int> myMap;
            
            int i,temp;
            int length = numbers.size();
            map<int,int>::iterator it;
            myMap.insert(pair<int,int>(numbers[0],0));
            for (i=1;i<length;i++)
            {
                temp = target - numbers[i];
                it = myMap.find(temp);
                if (it!=myMap.end())
                {
                    result.push_back(it->second+1);
                    result.push_back(i+1);
                    break;
                }
                myMap.insert(pair<int,int>(numbers[i],i));
            }
            //cout << result[0] << " " << result[1]<<endl;
            return result;
    
        }
        
    };

    呵呵,Accepted。一步一步的来,我还是不错的嘛。

    问题再次被解决,并且算法更简单。

    算法还能不能进行优化呢,如果可以,你就需要考虑复杂度O(lgn),看到这个时间复杂度,我们可以联想到排序后的数组进行二分查找时的时间复杂度。但是题目给的数据不一定是排序后的数据啊,因此这种方法不可行,也没用更好的算法。

     3.总结

    做算法题,可以先想出最直接,最简单的算法,计算复杂度,然后在此基础上一步一步的优化,最终找到满意的算法为止。

  • 相关阅读:
    .Net几大优点
    小谈.NET下的缓存。
    ASP.NET 防盗链的实现[HttpHandler]
    给网页加个个性的图标
    四个字节整型转换为IP格式
    在 ASP.NET MVC 中使用带后缀的 URL
    Visual Studio 2008 安装 SP1 后智能提示变英语的修补程序 (KB957507)
    Visual Studio 2008 SP1 安装失败的解决方法
    关于0x0d和0x0a回车换行\r和\n
    图像处理工程师的要求
  • 原文地址:https://www.cnblogs.com/LCCRNblog/p/4369257.html
Copyright © 2020-2023  润新知