Day1
刷题第一天,不知道自己可以坚持几天,慢慢来。。
PS:这是我第一次写博客,有很多不足的地方,很多地方也没有说的很清楚,没有把我想表达的东西表达出来,希望大家见谅!
题目描述
两数之和:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
原题地址点这里
解法一
最开始看到这道题我的想法就是直接两层循环一个个来查找。思路非常简单,代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int length = nums.size();
vector<int> result;
for(int i=0; i<length; i++) {
for(int j=i+1; j<length; j++) {
if(nums[i] + nums[j] == target) {
result.push_back(i);
result.push_back(j);
}
}
}
return result;
}
};
解法二
正所谓精益求精,可以明显看到解法一耗费的时间和空间都非常大,因此这显然不是一个好的解法,那我们要怎么改进呢?
通过观察解法一的代码,我们发现主要是两层循环需要耗费大量的时间,因为这是一个O(n2)时间复杂度的算法,因此我们需要想办法降低他的时间复杂度。那么我们要怎么做呢?请看下面的代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result(2);
vector<int> temp(nums);
sort(temp.begin(), temp.end());
int length = nums.size();
int i=0, j=length-1;
while((temp[i]+temp[j]!=target) && (i<j))
{
if(temp[i]+temp[j] > target) j--;
else i++;
}
result[0] = search_index(nums, temp[i], -1);
result[1] = search_index(nums, temp[j], result[0]);
return result;
}
int search_index(vector<int> nums, int value, int flag){
int j = nums.size();
int index = 0;
for(int i=0; i<j; i++) {
if(nums[i] == value) {
if(i != flag) {
index = i;
}
}
}
}
return index;
}
};
我们先是创建了一个给定vector的副本,之后对其进行由小到大排序,之后用最小的元素(排序后vector的第一个元素)加上最大的元素(排序后vector的最后一个元素),如果他们的和大于要找的target,那么就把最后一个元素的下标往前移;反之,若是小于则把第一个元素的下标往后移,直到找到等于target为止。
我在网上的一些地方也看到了类似的方法,他们把它称为“首尾递进查找”,我也不太记得我当时是怎么想到这个方法的了,也许是借鉴了其他人的想法。最后贴一张提交截图。
这是当时第一次做的时候提交记录:
这是我最近提交的,同样的代码不知道为什么时间差距这么大。。。。但是比起解法一,进步还是蛮大的。
解法三
这个方法是我看了LeetCode官方给出的答案,不得不说我还是太嫩了,简而言之就是菜。话不多说,上代码:
class Solution {
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");
}
}
这种方法就是巧妙的利用了哈希表查找时很低的时间复杂度(O(1)),只需要一次遍历即可找到这两个目标元素的下标,实在是妙啊。附上提交截图:
可以发现,虽然时间非常少,但是空间开销还是特别大的,因为哈希表需要耗费较多的空间资源吧,这也是一种空间换时间的方法。
总结
这只是Leet Code上一道十分简单的题目,但是想把它做好还是有一点难度的,不得不说算法这个领域真是博大精深,希望大家一起努力,一起进步!!