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].
Solution:
1、先想到了两遍for循环,暴力解法,但是转念一想,肯定有其他方法可以降低时间复杂度,于是就有了第一种错误的方法。
排序后使用头指针和尾指针来做。
错误点:这样做忽略了给定的array元素位置不可变的前提(如果可以改变的话,返回下标还有什么意义呢?)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
sort(nums.begin(),nums.end());
int begin = 0;
int end = nums.size() - 1;
while(begin < end) {
if (nums[begin] + nums[end] > target) {
end --;
}
else if(nums[begin] + nums[end] < target) {
begin ++;
}
else {
res.push_back(begin);
res.push_back(end);
break;
}
}
return res;
}
};
2、还是延续了上面的思路,接下来准备把排序之后的array存起来,然后在遍历一遍,找到原始array对应的两个值的下标,最后返回。
错误点:内存超了。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
vector<int> tmp = nums;
sort(tmp.begin(),tmp.end());
int begin = 0;
int end = tmp.size() - 1;
while(begin < end) {
if (tmp[begin] + tmp[end] > target) {
end --;
}
else if(tmp[begin] + tmp[end] < target) {
begin ++;
}
else {
break;
}
}
int i = 0;
while (i < nums.size()) {
if (nums[i] == tmp[begin]) {
res.push_back(i);
}
if (nums[i] == tmp[end]) {
res.push_back(i);
}
}
return res;
}
};
3、上面的方法行不通,还是需要遍历两遍来做。
c++:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for (int begin = 0; begin < nums.size()-1; begin++) {
for (int end = begin +1; end < nums.size(); end++) {
if (nums[begin] + nums[end] == target) {
res.push_back(begin);
res.push_back(end);
return res;
}
}
}
return res;
}
};
python:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
begin = 0
res = []
while begin < len(nums) - 1 :
end = begin +1
while end < len(nums) :
if nums[begin] + nums[end] == target:
res.append(begin)
res.append(end)
return res
end += 1
begin +=1
4、看了官方给的solution,的确可以用空间换时间,这里需要变换的想到两个点:一个是a + b = c 也可以写为 a = c - b; 另一个是可以使用map将a和a的下标存起来。最后只需要判断(c - b)是否在map中就可以了。
易错点:题目中明确说明了,一个元素不会使用两遍,所以还需要添加判断条件,a, b的下标是否一致。
c++ :
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
map<int,int> tmp_map;
for (int begin = 0; begin < nums.size(); begin++) {
tmp_map[nums[begin]] = begin;
}
for (int begin = 0; begin < nums.size(); begin++) {
if (tmp_map.find(target - nums[begin]) != tmp_map.end() && begin != tmp_map[target - nums[begin]]) {
res.push_back(begin);
res.push_back(tmp_map[target - nums[begin]]);
return res;
}
}
return res;
}
};
python:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
res = []
tmp_map = {}
it = 0
while it < len(nums):
tmp_map[nums[it]] = it
it += 1
it = 0
while it < len(nums):
if (target - nums[it]) in tmp_map and it != tmp_map[target - nums[it]]:
res.append(it)
res.append(tmp_map[target - nums[it]])
return res
it += 1
5、更好的写法:
这个是针对语法来说的,别人的可能写的更好,更加精简。
c++:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); ++i) {
unordered_map<int,int>::iterator iter = map.find(target - nums[i]);
if (iter != map.end())
return {iter->second, i};
map[nums[i]] = i;
}
//error comes up if there isn't this last "return" line.
return {0,1};
}
};
python:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
Dict = {}
for i in range(len(nums)):
if target - nums[i] in Dict:
return [i,Dict[target-nums[i]]]
else:
Dict[nums[i]] = i
6、其他
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。