大家好,我是算法小白,我所选的题目从codetop挑选codetop,这是一个很好的刷算法题网站,适合即将面试或者准备面试大厂的老铁。
这一题是一道用空间代替时间的题(给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标)。
看到题目,首先会想到暴力解,双for循环来枚举所有解,得到结果返回,
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
if(nums[i]+nums[j] == target){
return new int[]{i,j};
}
}
}
当然这种解法最坏的情况每个数都要匹配一次,时间复杂度O(n^2)
所以内层的for循环可以进行一个优化,开辟一道内存hash表去替代。
for (int i = 0; i < nums.length; i++) {
if(cache.containsKey(target - nums[i])){
return new int[]{cache.get(target-nums[i]),i};
}
cache.put(nums[i],i);
}
以值为key,索引为value,如果能从内存中找到target - nums[i]为key这条数据,那结果自然得到,
最终时间复杂度为O(n)。
如果在此基础上进行拓展,求三数之和怎么办?前面已经求出两数之和,我们可以把两数之和看出一个函数twoSum,三数之和不就是twoSum(target - num[i]),如果返回值不为空不就得出结果么,
public static int[] twoSum2(int[] nums, int target,int index) {
Map<Integer,Integer> cache = new HashMap<>();
for (int i = index; i < nums.length; i++) {
if(cache.containsKey(target - nums[i])){
return new int[]{cache.get(target-nums[i]),i};
}
cache.put(nums[i],i);
}
return null;
}
public static int[] threeSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
int[] cur = twoSum(nums, target - nums[i], i + 1);
if(cur!=null) {
int[] array=new int[cur.length+1];
for (int x = 0; x < cur.length; x++) {
array[x] = cur[x];
}
array[cur.length] = i;
return array;
}
}
return new int[]{0};
}
N数之和怎么办?三数之和依赖两数之和,那N数之和自然依赖N-1数之和,这不就是一个递归么,我们只要把两数之和求出自然会求出N数之和,
public static int[] nSum(int[] nums, int n ,int index,int target) {
if(n == 2){
return twoSum2(nums, target, index);
}else {
for (int i = index; i < nums.length; i++) {
int[] cur = nSum(nums, n-1, i + 1,target - nums[i]);
if(cur!=null) {
int[] array=new int[cur.length+1];
for (int x = 0; x < cur.length; x++) {
array[x] = cur[x];
}
array[cur.length] = i;
return array;
}
}
}
return new int[]{0};
}