题目(难度:简单):
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
例如:
给定 nums = [2, 7, 11, 15], target = 9.
解决办法(暴力):
public class Solution01{
public int[] twosum(int[] nums,int target){
int[] ints = new int[2];
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
ints[0]=i;
ints[1]=j;
}
}
}
return ints;
}
public static void main(String[] args){
int[] nums = {1,2,5,7,9};
Solution01 solution01 = new Solution01();
int[] ints = solution01.twosum(nums,9);
for(int i=0;i<ints.length;i++){
System.out.print(ints[i]+" "); //output:1 3
}
}
}
缺点:(1)拓展了额外的数组空间;【因为题目里限制了返回类型为int[],故这一项不可解决】
(2)复杂度高;
(3)只能给出满足两个数之和等于target的一组数。
解决(3)后的代码如下:
public class Solution01{
public int[] twosum(int[] nums,int target){
int[] ints = new int[nums.length+1]; //考虑极端情况,数组两两之和均为target
int m = 0;
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
ints[m++]=i;
ints[m++]=j;
}
}
}
ints[m]=-1; //因为ints数组存储的是nums数组的下标,所以不存在负数可放心使用
return ints;
}
public static void main(String[] args){
int[] nums = {1,4,6,7,9,3};
Solution01 solution01 = new Solution01();
int[] ints = solution01.twosum(nums,10);
for(int i=0;ints[i]!=-1;i++){
System.out.print(ints[i]+" "); //output:0 4 1 2 3 5
}
}
}
最终版:
思想:利用map,键存储数组元素值,值存储数组下标,再利用一个临时变量存储target-nums[i],即目标值与数组元素值的差值,利用map.containKey()方法判断,若map里面存在则恰好等于target,否则存入map。
public static int[] twosum(int[] nums,int target){
if(nums==null&&nums.length<2){
return null;
}
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
return new int[]{map.get(temp),i};
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("No Result");
}
测试用例:
算法分析:
时间复杂度O(n),空间复杂度O(n)
另解(数组实现):
若该题是数组已经排好序或者将数组排好序后,利用两个变量 i 和 j,分别指向数组的最左端(min)和最右侧(max)
(1)当 i < target时,判断nums[i]+nums[j]是否等于target
(2)当i>=target时,结束循环
前提条件是i < j。