题目链接 两数之和
题目描述(当时直接复制粘贴的时候,编辑界面就卡住,需要看题目的请打卡链接)
题目大意:
给定一个数组和一个target,在这个数组中找到两个数的和等于这个target,并返回他们在数组中的下标。
示例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解题思路
解法一
暴力解法,时间复杂度O(n*n),空间复杂度O(n)。对于所给的数组进行两边for循环,为的就是把所有不重复的两个数的组合找出来,看其之和是否与target相等,相等就返回各自的下标。
程序代码
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)
//找寻两种不同的数字组合,看其和是否等于target
if(nums[i]+nums[j]==target) return {i,j};
return {};
}
};
解法二
时间复杂度o(nlogn)空间复杂度o(n)
利用c++中的map函数,我们可以先将nums数组的值和下标存入map中,然后我们可以利用target-nums[i]是否在存在map中进行查找,就可以得到答案。
class Solution {public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int> m;
//for(int i=0;i<nums.size();++i) m[nums[i]]=i;
for(int i=0;i<nums.size();++i) {
if((m.find(target-nums[i])!=m.end())&&(m[target-nums[i]]!=i))
return {i,m[target-nums[i]]};
m[nums[i]]=i;
}
return {};
}
};
解法三
其实我觉得解法三跟解法二一样,只是刚开始的先进行了赋值操作m[nums[i]]=i;把上面的程序中注释掉的那一行加进去,把程序中的 m[nums[i]]=i; 删掉。
解法四
解法四跟解法二差不多,只是这里没有用到map,直接是用数组的有序性来进行hash的,适用于nums中的数值不是很大的情况,如果数值很大,空间就会炸掉。
解题反思
这道题最容易想到的就是解法一,但是一旦对时间要求更加严格,就不能够a掉。而时间复杂度主要就是耗费在查找第二个数上,这个时候就应该得想想,有没有什么时间复杂度更低的查找方法。而知道的一些查找方法里面有二分查找、map的是用、平衡树等等,利用树结构查找时间基本都在log n,而这里为了方便操作,我们就采用map。
Leet Code 如何提交代码
在LeetCode提交代码和洛谷、hdu、pku、bzoj等不太一样,洛谷、hdu、pku、bzoj这一类的网站是需要提交一个完整的程序,但是LeetCode只需要提交一个函数。
以上面的例题来讲,LeetCode上面会帮你把class、public、vector类似这样的代码写好,也就是给你先写一个模板。数据啥的会自动存储在nums、target里面,相当于现在我们只需要写一个函数,把最后需要输出的值像在函数中那样返回到主程序当中。(也可以理解为在LeetCode上面他已经帮你把数据输入好了,现在我们只需要用输入好的数据以及定义好的变量继续往下写代码就好了,跟在函数中写程序一样。)