简评
这是Leetcode 001号 题目,本以为是一道超级简单题。(实际上也确实是)基本的解题思路的确是编程入门者也能写出来。不过我在看了solution之后才发现原来还有很大的优化空间,可以把算法时间复杂度从 O(n^2)优化到O(n)的级别。不过事难两全,相对于的空间复杂度就要从O(1)退化到O(n)。
本文从我的个人博客转来,全文除注明外原创。
题目
英文原文
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.
官方中文
给定一个整数数列,找出其中和为特定值的那两个数。
你可以假设每个输入都只会有一种答案,同样的元素不能被重用。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
解法一(暴力枚举、遍历)
思路分析
不难想到:从第一个数直到倒数第二个数,检验每个数从其后一个开始直到最后一个数和它相加的和,如果等于target则返回这两个数的索引。
这种方法简单容易想到。代码实现也较为容易。
解法一AC代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for( int i = 0; i < nums.size() ; ++i){
for( int j = i + 1 ; j < nums.size() ; ++j){
if( nums[i] + nums[j] == target){
vector<int> ans = {i,j};
return ans;
}
}
}
}
};
时间:113ms
解法二(Hashtable)
思路分析
这个解法来自solution。C++自带了hashtable的数据结构。关键字为map。这种结构通过计算元素的hash值来得出元素在内存中的位置。从而实现近乎O(1)的元素插入删除查找效率。之所以达不到,则是因为hashtable本身需要扩容。hashtable需要以(key,value)的形式成对存入数据。其中key作为数据在哈希表中的索引,value为该索引对应的值。因此,可以得出以下思路:应当把数据本身作为key,而数据在array中的索引作为value存入哈希表中。从第一个数nums[1]开始,直到最后一个数,检查 target - nums[i] 是否在 hashtable 中,如果在,则返回i值和target - nums[i] 对应的value值。如果不在,则把(nums[i],i)存入哈希表中。
解法二AC代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int , int> nums1;
for( int i = 0 ; i < nums.size() ; ++i){
int num = target - nums[i] ;
if( nums1.count( num ) ){
if( i < nums1[num]){
vector<int> ans= {i , nums1[num] };
return ans;
}
else{
vector<int> ans= { nums1[num] ,i };
return ans;
}
}
nums1[ nums[i] ] = i;
}
}
};
时间:9ms