[LeetCode]1. Two Sum

# 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 twoSum(vector& 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 twoSum(vector& nums, int target) {
        map 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 twoSum(vector& nums, int target) {
        unordered_map 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实现,因此查找、插入和删除速度比较快。

你可能感兴趣的:([LeetCode]1. Two Sum)