2020-04-03

作者: 七八音 | 来源:发表于2020-04-03 22:32 被阅读0次

    # 1.Two Sum

    题目

    Given an array of integers, return indices of the two numbers such that they add up to a specific target.

    You may assume that each input would have exactly one solution, and you may not use the same element twice.

    Example:

    Given nums = [2, 7, 11, 15], target = 9,

    Because nums[0] + nums[1] = 2 + 7 = 9,
    return [0, 1].

    给定一个整数数组nums和一个整数target,在数组中查找两个数使得两数之和等于target,最终返回这两个数在数组中的下标。

    我们可以设定每个输入都有一个解,同一个数字不能用两次。

    例子中,2+7=9,所以返回的数组为[0,1].

    最简单

    最容易想到的方法是数组遍历,使用两层循环,找到target的解。

    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            if (nums.empty()) return {};
            for (int i=0; i< nums.size(); i++){
                for (int j=i+1; j< nums.size(); j++){
                    if (nums[i] + nums[j] == target)
                        return {i, j};
                }
            }
            return {};
        }
    };
    

    这种方法虽然简单,但是耗时比较长。时间复杂度为O(N^2).

    方法二 map

    算法中一个常见的降低耗时的方法是空间换时间。应用在这里就是说,我们将数组存储在一个可以直接查找数值的数据结构中,这个数据结构存储数值和对应下标,这种数据结构可以称为字典。键是数值,值是下标。

    这里没有必要先将所有的数值都存储在数据结构中,可以一边遍历数组,一遍进行数值存储(数据结构的赋值)。

    CPP中我们可以使用map容器进行数值存储。代码如下:

    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            map<int, int> dict;
            for (int i=0; i< nums.size(); i++){
                if (dict.find(target-nums[i]) != dict.end())
                    return {dict[target-nums[i]], i};
                dict[nums[i]] = i;
            }
            return {};
        }
    };
    

    CPP中除了可以使用map容器外,还可以使用unordered_map容器,代码如下:

    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            unordered_map<int, int> dict;
            for (int i=0; i< nums.size(); i++){
                if (dict.find(target-nums[i]) != dict.end())
                    return {dict[target-nums[i]], i};
                dict[nums[i]] = i;
            }
            return {};
        }
    };
    

    两者代码基本上相同,除了数据声明不同。

    三种方法耗时,内存占用情况如下。

    image-20200403221647958.png

    可以看到,方法二相较于方法一的两层循环在耗时上优化很大,但是代价是内存占用的增加。此外,unordered_map与map相比耗时更少,但内存占用是最多的。

    小结

    1. 时间换空间,空间换时间。两者是一个比较矛盾的方面,如果方法耗时较长,我们可以想办法将部分结果存储起来,可能会减少耗时。
    2. map和unordered_map两者底层实现的数据结构不同。map插入元素之间是有顺序的,unordered_map元素之间没有顺序;map底层实现基于AVL树,当元素插入导致树不再平衡时,需要进行调整;unordered_map底层基于hash实现,因此查找、插入和删除速度比较快。

    相关文章

      网友评论

        本文标题:2020-04-03

        本文链接:https://www.haomeiwen.com/subject/isilphtx.html