【被OJ毒打的第一天】LeetCode_简单_1.两数之和
题干:
给定一个整数数组 nums 和一个整数 target,请你在该数组中找出和为 target 的那两个整数,并用一个
二维整数数组的形式返回他们的数组下标
提示:
假设每种输入只对应一个答案
不能重复使用这个数组中同样的元素
输入:
nums = [1,2,7,3]
target = 9
输出:
[1,2]
1.普通做法
执行用时:256ms,9.3MB
作为一个懒人,首先用最不需要思考的办法过了再说......
思想:两层循环,遍历所有求和情况,理论上时间复杂度是
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (nums[i] + nums[j] == target) {
res.push_back(i);
res.push_back(j);
break;
}
}
}
return res;
}
2.进阶做法
执行用时:16ms,10.2MB
执行时间恰好是刚才那个方法的平方根,说明此方法时间复杂度应为
思想:鉴于哈希容器的查找 map.find() 时间复杂度为 ,用空间换时间
实现:遍历一次 nums,将 (nums[i], i) 的键值对存入一个 map;遍历过程中,如果在 map 中找到 target - nums[i] ,就说明当前值和之前的某个值和为 target,故可以将当前的 i 和 map[target - nums[i]] 的值作为结果返回
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
map<int, int> pairs;
for (int i = 0; i < nums.size(); i++) {
int x = target - nums[i];
if (pairs.find(x) != pairs.end()) {
res.push_back(pairs[x]);
res.push_back(i);
return res;
}
pairs[nums[i]] = i;
}
return res;
}
3.神仙做法
执行用时:12ms,10MB(多执行几次发现其实也并不是每次都这么快)
思想:在方法2的基础上,使用效率更高的 unordered_map
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> ret;
unordered_map<int, int> mp;
size_t vec_len = nums.size();
for(size_t i = 0; i < vec_len; ++i) {
int diff = target - nums[i];
unordered_map<int, int>::iterator it = mp.find(diff);
if((it != mp.end()) && (i != it->second)) { // 确保不重复使用同一元素
ret.push_back(it->second);
ret.push_back(i);
break;
}
mp[nums[i]] = i;
}
return ret;
}
算法真实毒打我,解决问题我可,提高效率实难emmm
继续加油吧!