题目:
分析:
题目中已经提示了每种输入只会对应一个答案,也就是说这个数组是一个比较特殊的数组,数组中两个数相加得到的目标值target是唯一的,不可能存在多对两个数相加得到同一个目标值target,也就是说我们得到了两个数相加的值等于target了,这个时候我们可以直接返回,因为每种输入只会对应一个答案,后面不会存在其他两个数相加等于目标值target的情况。
蛮力解法:
public class TwoSum {
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length-1; i++) {
for (int j = i+1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[]{
i, j};
}
}
}
return null;
}
public static void main(String[] args) {
System.out.println(Arrays.toString((new TwoSum().twoSum(new int[]{
3,2,4},6))));
}
}
优化分析:
可以看到题目要求我们返回的两个数是有关联的,我们把这两个数定义为numA和munB,他们的关系为:numA+numB=target
numB=target - numA
也就是说如果其中一个数是numA,那么其中另外一个数一定是target - numA
此时我们可能会产生这样的想法,既然两个数都和numA有关联,target是一个已经确定的值,我们在第一层遍历的时候能否记录一下相关的数值,来减少循环次数呢?
也就是说我们能否在外层遍历的时候,记录一些相关信息,以省去内层的一层循环。
下面这种方法用到的查找表法来记录相关信息,记录的相关信息为:外层遍历过的数值,以及它所对应的下标
查找表法一般来说有两种实现方式:哈希表和平衡二叉搜索树,这里我们不需要维护查找表中元素的顺序,所以我们选择用哈希表来做。
优化代码:
public class TwoSumNew {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
int length = nums.length;
//初始化时指定长度,避免后续扩容影响性能
Map<Integer, Integer> map = new HashMap<>(length-1);
for(int i = 0; i < length; i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
}
map.put(nums[i], i);
}
return res;
}
public static void main(String[] args) {
System.out.println(Arrays.toString((new TwoSumNew().twoSum(new int[]{
3,2,4},6))));
}
}