LeetCode初级算法之数组:两数之和

题目描述
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路一: 暴力

这个题最容易想到的就是暴力解法,直接两次循环,外循环遍历,内循环从外循环位置的后一个位置开始找,如果两个数之和为target,就把这两个数的下标存入res数组返回。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int len = nums.size();
        vector<int> res;

        for (int i=0; i<len; i++)
        {
            for (int j=i+1; j<len; j++)
            {
                if (nums[i] + nums[j] == target)
                {
                    res.push_back(i);
                    res.push_back(j);
                }
            }
        }
        return res;
    }
};

优点: 思路简单直接暴力
缺点: 时间复杂度太高 O(n^2)
这样即使做出来意义不太大,毕竟时间和空间上没有一点占优势,有啥用?
所以,还有一个改进的版本,就是哈希表的思想

思路2: 哈希表映射

我们知道,这个题既需要数值比较,也需要下标返回,对应数值和下标最好的方式就是map数组,并且map的查找效率也比较优秀。 所以这个题不妨采用map的优良性质。
遍历一遍数组, 对于当前的数nums[i],我判断target-nums[i]是否在map的键当中,如果在,说明m[target-nums[i]]和i这是一组答案,放入res数组, 如果不在,那么按照<nums[i], i> 的形式存入map, 遍历结束,返回res数组即可。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int len = nums.size();
        vector<int> res;
        map<int, int> m;

        for (int i=0; i<len; i++)
        {
            if (m.count(target-nums[i]))
            {
                res.push_back(m[target-nums[i]]);
                res.push_back(i);
            }
            m[nums[i]] = i;
        }
        return res;
    }
};

优点: 遍历一遍数组即可,时间复杂度降为O(n)。
有时候map还是比较好用的。

小总:

解决问题的时候,不要仅仅把思维限制在解决了这个问题,还应该考虑一下是不是以一个比较好的方法解决了这个问题,不能总是蛮干,思维要开放一些,这样学习的效果才会更好,其实,如果单单说解决问题的话,大部分题目,暴力都可以解决,暴力就行了,当然实际中,比较实用的方法依然可能是暴力,但是至少优化,这不仅是一种思维方式,还是一种实际运用中努力的方向。所以解决完一个问题之后,最好是分析一下该方法的时间复杂度和空间复杂度,再思考一下有没有能够在这两方面有改进的方法,哪怕只有一点改进,对自己的思想模式来说也是一种进步,毕竟,这不仅仅是一个题目那么简单,而是一种思考问题的方式,相对于解决一个问题来说,如何思考这个问题更显得重要一些。

发布了66 篇原创文章 · 获赞 67 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wuzhongqiang/article/details/103211693