问题描述:
给定一个整数数组,找到和为零的子数组。你的代码应该返回满足要求的子数组的起始位置和结束位置
样例
给出 [-3, 1, 2, -3, 4]
,返回[0, 2]
或者 [1, 3]
这个问题比较好想的算法的时间复杂度是O(n^2),这不是我们希望看到的。
要解决这个问题我觉得需要明白两点:
1.一个子数组的和为零,我们假设这个子数组是{ a[i], a[i+1], ..., a[j] },也就是a[i] + a[i+1] +...+ a[j] = 0,起始和结束位置其实就是i和j。那么 a[0] + a[1] +...+ a[i-1] + a[i] + a[i+1] +...+ a[j] = a[0] + a[1] +...+ a[i-1] 。把这个式子转换下,假如这个数组的前 i 项的和与前j项的和相等,那么i项到j项之间的数组的元素的和肯定是零。i,j就是需要的结果。
所以这个问题就转换成了求数组前n项和的问题
2.假如前 i 项的和为零,那么0 和 i 即为所求结果
我提供一种O(n)的解法,希望对大家有所启发
public List<Integer> subarraySum(int[] nums) {
// write your code here
ArrayList<Integer> list = new ArrayList<>();
int[] sumArrays = new int[nums.length];
sumArrays[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sumArrays[i] = sumArrays[i-1] + nums[i];
}
HashMap<Integer, Integer> indexsMap = new HashMap<>();
for (int i = 0; i < sumArrays.length; i++) {
if (sumArrays[i] == 0) {
list.add(0);
list.add(i);
return list;
}
if (indexsMap.containsKey(sumArrays[i])) {
list.add(indexsMap.get(sumArrays[i])+1);
list.add(i);
return list;
}
indexsMap.put(sumArrays[i], i);
}
return list;
}