leetcode 1 两数之和
题目
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解题思路
1、最简单做法,遍历所有情况,复杂度O(n2)
2、先排序,头尾加两个指针,向中间移动,若指针和小于target,则尾指针前移,若指针和大于target,则头指针后移,复杂度取决于排序算法,最快O(nlogn)
3、不排序,用hash存每个数出现的次数,第一次遍历找出num1,判断条件是target-num1存在且不为同一个num1,如:(3,2,4),target为6,num1为3,target-num1也为3,同一个3就不行。但是如:(3,3),target为6,则num1的3和target-num1的3不为同一个,即可;第二次遍历,找出target-num1的位置,若遇到num1直接跳过,避免重复的情况发生(题目要求同样元素不能重复利用)。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i,len = nums.size();
map<int, int> mark;
mark.clear();
for(i=0; i<len; ++i) {
mark[nums[i]] ++;
}
int le, ri;
for(i=0; i<len; ++i) {
mark[nums[i]] --;
if(mark[target - nums[i]]) {
le = i;
break;
}
mark[nums[i]] ++;
}
for(i=0; i<len; ++i) {
if(i == le) continue;
if(nums[i] == target-nums[le]) {
ri = i;
break;
}
}
vector<int> v;
v.push_back(le);
v.push_back(ri);
return v;
}
};
解题思路(最新最简洁)
1、思路同上,代码简化。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i,len = nums.size(),rest = 0;
map<int, int> mark;
vector<int> ans;
for(i = 0; i < len; i++)
mark[nums[i]] = i;
for(i = 0; i < len; i++){
rest = target-nums[i];
if(mark[rest] && mark[rest] != i){ //mark[nums[i]]存的是num[i]最后出现的位置,那么只要不是同一个nums[i],就直接保存结果
ans.push_back(i);
ans.push_back(mark[rest]);
break;
}
}
return ans;
}
};
2、一次遍历哈希表,在遍历的同时,存下当前的哈希值,并且在每遍历一个元素时直接查找哈希表中是否已经存在满足条件的值
java:
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}