1.Two Sum
Posted ovs98
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.Two Sum相关的知识,希望对你有一定的参考价值。
Description
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].
题目传送门
一.题目理解
这是LeetCode的第一道题目,LeetCode和之前刷的OJ有些不同,不用完全提交程序(包含main函数),是侧重算法的,我们只需要完成算法就好。
下面说题目:这道题很好理解,给定一个数组,里面有很多整数,然后给定一个目标值,题目假设数组中刚好有两个数字之和等于目标值,我们需要找到这两个数字,并返回其下标。
二.题目解答
1.暴力求解
1.1 思路和代码
首先能想到的就是暴力求解,这种方法很简单,但是效率不高。
//Brute Force class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> ret; for(int i = 0;i < nums.size();i++){ for(int j = i + 1;j < nums.size();j++){ if(nums[i] + nums[j] == target){ ret.push_back(i); ret.push_back(j); break; } } } return ret; } };
1.2 复杂度分析
- 时间复杂度:O(n2) .对每一个元素,我们都要搜索剩余元素中有无匹配元素(两者之和为目标值),每一个元素花费的时间为O(n),总的时间为 O(n2).
- 空间复杂度:O(1).
1.3 效果
2.优化
这里的优化主要是根据Solution的指导而来,有两种优化Two-pass Hash Table, One-pass Hash Table。
2.1 Two-pass Hash Table
2.1.1 思路和代码
为了降低时间复杂度,我们应该采用一个更合理的方式去进行匹配元素的搜索,由题目我们可以知道匹配元素一定存在且唯一,同时要求返回匹配元素的下标;考虑到匹配元素和其下标的匹配,自然联想到Hash表。
通过哈希表我们可以把搜索一个元素的匹配元素的花费由O(n)降为O(1),不过代价是增加了空间开销,我们需要存储哈希表。尽管哈希表在有碰撞的情况下搜索花费能达到O(n),但是本题目刚好是有唯一解,这也就表示碰撞不会发生,因而我们可以大胆采用哈希表。
由于匹配元素是唯一的,所以我们可以考虑无序表unorderded_map,使用元素的具体值作为键值,其下标作为映射值。
//Two-pass Hash Table class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int,int> m; vector<int> ret; for(int i = 0; i < nums.size(); i++) m[nums[i]] = i; for(int i = 0; i < nums.size(); i++) { int complement = target - nums[i]; if(m.count(complement) && m[complement] != i) { ret.push_back(i); ret.push_back(m[complement]); break; } } return ret; } };
2.1.2 复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)
2.1.3 效果
2.2 One-pass Hash Table
2.2.1 思路和代码
上述的结果证明我们的思路是正确的,其实我们还可以继续优化,可以在生成哈希表的过程进行搜索,从而进一步提高速度,降低时间复杂度。
//One-pass Hash Table class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int,int> m; vector<int> ret; for(int i = 0;i < nums.size();i++){ if(m.count(target - nums[i])){ ret.push_back(i); ret.push_back(m[target-nums[i]]); return ret; } m[nums[i]] = i; } } };
2.2.2 复杂度分析
- 时间复杂度: O(n)
- 空间复杂度: O(n)
2.2.3 效果
以上是关于1.Two Sum的主要内容,如果未能解决你的问题,请参考以下文章