问题一:两数之和
描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。你可以按任意顺序返回答案。
分析:
问题中确认每种输入只会对应一种答案,所以不存在这种情况[0 1 2 4 4 5 target = 9,输出答案4 5,4’ 5,不会有重复的元素4作为5的另一半。所以一旦重复元素作为返回答案,那么只能有一种可能:target=8 返回 4,4]
解题思路一:
1.n数之和可以使用hashmap来解决。具体解题思路:
前提:初始化一个hashmap,key=nums[i] value = i
第一步:我们判断输入的nums是否合法,如果不合法直接返回空结果
第二步:我们遍历数组nums,遍历位置为i(0–>length-1);判断target-nums[i]是否存在于hashmap的key中。
①如果不存在,那么就把当前值需要放入hashmap中,放入前需要判断hashmap中是否存在nums[i],
1)如果存在,说明之前有这个重复元素,因为重复元素作为答案只能是两个值都是该元素,所以判断(nums[i])*2==target? 如果成立,停止遍历,返回结果。如果不成立,结束遍历,继续下次遍历。
2)如果不存在,将nums[i]->i 放入hashmap中。
②如果存在,证明两数之和=target等式成立,结束遍历,返回结果即可。
第三步:如果遍历完成后没有答案,直接返回空
实现代码:
class Solution {
public int[] twoSum(int[] given, int target) {
return twoSumSoult_2(given,target);
}
private int[] twoSumSoult_2(int[] given, int target) {
// hash: value->index 假如 给定数据 1 2 3 3 4 target = 6 应该返回 2 ,3 不应该返回2,2
// 所以使用hash的时候要注意,别被替换了下标
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
ArrayList<Integer> subValue = new ArrayList<>();//把target-value的值放入list里面,如果遍历中发现了这个值,就直接返回结果
for(int i=0;i<given.length;i++){
if(subValue.contains(given[i])){
return new int[]{map.get(target-given[i]),i};
}
if(map.getOrDefault(given[i],-1)==-1){
map.put(given[i],i);
subValue.add(target-given[i]);
}else{
if(given[i]*2!=target){
continue;
}else{
return new int[]{map.get(given[i]),i};
}
}
}
return new int[]{};
}
}
解题思路二:
1.可以选择在一个有序队列中,使用双指针来进行求解:
前提是该队列为有序队列[0 1 2 3 4 5 6 7 target = ‘13’ 返回结果:6 7 ]
第一步:初始化两个指针,一个指向最小值nums[i],一个指向最大值nums[j]。
第二步:判断sum= (nums[i]+nums[j]) 与target的大小
while(true){
①if sum > target j–
②if sum < target i++
③if sum = target 返回答案
}
第三步:如果遍历结束没有答案,返回空
特殊提示:
1.输入数组必须有序,也就是使用前需要排序。并且记录数的原始下标位置
2.排序之后,使用双指针求解,求解结束后,按照当前的值取寻找原始下标并返回结果
3.在记录下标的时候,会有记录重复元素的情况,重复的元素解决方案由上文方法一提供。