一、两数之和
1、问题描述

2、问题提示

3、分析
给定数组,要求从数组中抽取两个不等的元素a,b来构成a+b=target;
3.1 使用排序后指针夹击法
描述:当一个数组是有序的,那么如果要求
a,b之和等于target,那么可以把数组最小的值代为a,数组最大的值代为b,判断此时的a和b之和是否满足条件;
1)如果当前a和b之和大于目标值,可以将b左移,
2)反之可以将a右移。
3)如果在a和b重合之前找到符合条件的值,那么就返回当前a和b代入的值的当前下标。
4)如果a和b重合了,那么则没有答案。
5)此题所给数组是无序的,并且需要返回解的下标值。所以我们需要在排序前将之前元素的下标使用map记录下来。因为答案是唯一的,所以不需要担心key会重复。除非是相同的元素出现两次,并且这个元素*2恰好是答案。那么直接返回这俩元素下标即可。
5.1举例)数组:3 3 1 target:6 答案是 0 1。
5.2举例)数组 3 3 2 1 target:5 这个是不符合题意的,所以不用考虑。
6)最后我们可以拿到a和b的值去map中找到对应的下标。
3.1.2 实现代码
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.getOrDefault(nums[i],-1)!=-1){
if(nums[i]*2==target){
return new int[]{map.get(nums[i]),i};
}else{
map.put(nums[i],i);
}
}else{
map.put(nums[i],i);
}
}
Arrays.sort(nums);
int a = 0;
int b = nums.length-1;
while(a<b) {
while (a < b && (nums[a] + nums[b]) < target) {
a++;
}
while (a < b && (nums[a] + nums[b] > target)) {
b--;
}
if ((nums[a] + nums[b]) == target) {
return new int[]{map.get(nums[a]), map.get(nums[b])};
}
}
return new int[]{};
}
3.1.3 算法分析
时间复杂度:O(n)循环次数和数组长度成一次函数正比例。
空间复杂度:O(n)使用了map结构来存储数组元素,使用空间和数组长度成一次函数正比例。
3.2 使用map结构存储法
描述:首先实例一个map的映射结构。key是数组元素,value是数组下标。
1)遍历数组,遍历时逻辑如下,假如遍历到位置i,首先判断target-i是否存在map的value中。
2)如果不存在,那么map.put(nums[i],i);
3)如果存在,那么直接返回map.get(target-i)和i的下标
4) 注意,在遍历的过程中,同时需要判断是否元素冲突,如果冲突按照方法3.1.1的冲突来解决。
5)如果遍历完成之后,没有结果,那么返回空数组
3.2.1 代码实现
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.getOrDefault(nums[i],-1)!=-1){
if(nums[i]*2==target){
return new int[]{map.get(nums[i]),i};
}
}else{
if(map.keySet().contains(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}else{
map.put(nums[i],i);
}
}
}
return new int[]{};
}
3.2.2 算法分析
时间复杂度:O(n)循环次数和数组长度成一次函数正比例。
空间复杂度:O(n)使用了map结构来存储数组元素,使用空间和数组长度成一次函数正比例。
3.3 使用暴力破解
描述:
1.外层循环进行遍历,i从0开始到数组结束
2.内层循环j从i的后一位进行遍历
3.内层遍历逻辑:如果发现
i+j = targe那么直接返回结果,如果没有发现则返回空4.注意这里j是从i后面一位开始遍历,是因为j如果从0开始遍历,其实是和i从0开始遍历冲突,所以才选择j=
i+1
3.3.1 代码实现
public int[] twoSum(int[] nums, int target) {
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
return new int[]{i,j};
}
}
}
return new int[]{};
}
3.3.2 算法分析
时间复杂度:O(n^2) 循环次数和数组长度成二次函数正比例。
空间复杂度:O(1) 定义了两个循环变量i,j。没有开辟多余空间。
浙公网安备 33010602011771号