目录
1、本题地址和题目
本题是我在力扣上面做的,难度是简单级别,地址如下:
1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com)
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案
下面是示例和数据范围:
2、分析一下题目
题意是很容易理解的,就是要求从给定的一个整型数组中找出两个数,这两个数的和是给定的某一个数,然后以数组的形式返回这两个数的下标。这两个数的下标不能一样 ,但是这两个数可以是相等的。题目保证有唯一的答案。根据数据的范围,最大是 十的九次方,最小是十的负九次方,而JAVA整型的范围最小是负21亿多,最大是21亿多,使用基本的int类型就可以。
3、我的解法和代码
这个题是简单类型的,可以直接暴力破解,但是复杂度会非常的高,是O(n^2)。由于力扣不像牛客ACM有时间限制,我为了尽快解题,使用了暴力破解;
暴力破解就是枚举所有可能,直到找到答案:使用双重循环。外循环是从数组的第一位直到最后一位,内循环是从外循环那一位的后一位开始,直到最后一位。如果两数字的和等于给出的数字,那么就将两个下标存入结果数组中,然后跳出外循环,返回结果数组。
我的JAVA代码如下所示:
class Solution {
public int[] twoSum(int[] nums, int target) {
int result[]=new int[2];
int i,j;
a: for(i=0;i<nums.length;i++){
for(j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
result[0]=i;
result[1]=j;
break a;
}
}
}
return result;
}
}
可以顺利通过,但是复杂度是O(n^2),消耗内存和运行时间多。执行时间只超过26%的人,消耗内存只超过38%的人,不推荐。
4、优化算法和解析
上面的暴力破解法时间复杂度太高了,使用下面的解法降低时间复杂度:
题目就是需要我们从数组中找到两个数,这两个数的和为一个已知的数,并且答案还是唯一的。这就表明这两个数之间是有关系的。我们可以使用Map数据结构,对数组进行一次遍历。将数组中的数字作为Map的键(Key),将下标作为值(Value),这样做是因为我们最终要的就是两个下标,所以下标作为值是合理的。我们每遍历一个数组中的数字的时候,就要判断Map中是否存在跟它的和是题目所给数字的那个数,也就是是否存在与之对应的那个Key,如果存在,那么我们就找到答案了,不需要将正在遍历的这个数字存到Map中,可以返回答案。如果不存在(说明Map中没有它的另一半),那么我们就将遍历到的这个数字和它的下标存入Map中。最坏的情况就是,答案中的两个坐标,一个是0,另外一个是length-1,并且各不一样,遍历到最后,Map的长度就是(length-2)-0+1。这里我多说一下,我们不需要担心数组中有相同的数字,比方说吧target是10,数组中有两个4,那么这两个4的下标也不是正确答案,我们肯定会将放在前面的一个4先放入Map中,当我们遍历到第二个4的时候,还是需要将它放入Map中的,这时候两个4都要作为Key,就产生冲突了。但是在Map的存储机制下,如果两次要存入的Key一样,Map就只会对Value做出改变,或者你可以理解为,后面的覆盖掉了前面的。由于答案是唯一的,像上面我举的例子,存在两个4,并且target是10,那么数组中一定是没有6的,否则答案就不唯一了。
上面解法的时间复杂度是O(n),因为只遍历了一次,但是存储空间消耗稍多一点,因为使用了Map记录。空间复杂度也是O(n)
下面是我的JAVA代码:
public int[] twoSum(int[] nums, int target) {
int result[]=new int[2];
Map<Integer,Integer> map=new HashMap<>(nums.length);
map.put(nums[0],0);
for (int i=1;i<nums.length;i++){
if (map.containsKey(target-nums[i])){
result[0]=i;
result[1]=map.get(target-nums[i]);
break;
}else {
map.put(nums[i],i);
}
}
return result;
}
最后的情况是:
运行用时超过了前100%的用户,内存消耗超过了前63%的用户。
5、总结和收获
其实这一道题利用的就是Map的特性,键值是一一对应的。况且答案是唯一的,我们用空间换时间,利用了两个数之间的关系,即 两数之和已经确定了;
这道题要注意的是键和值得确定,键和值分别是什么。
学习的一些数据结构或者是特性,不能只停留在概念上,需要能够灵活使用。