Subarray Sum Equals K及其follow up
阿新 • • 發佈:2018-12-30
continuous sum equals K(follow up問了可以負數和0,最後又follow up 算最大長度)
nums = [1,2,3,4,5,4], k = 9, 求有多少個符合的subarray
分析:當陣列只有正數時雙指標的方法為最優,時間2*N,空間1,HashSet的方法也可以解,時間N,空間N
解法一:雙指標(陣列僅有正數,否則指標無法正確移動)
//兩個指標從頭開始,當sum小於k的時候,移動右指標,當sum大於k的時候,證明從左指標開始的subarray一定沒有答案了,因此移動左指標。依次下去直到遍歷結束。
//能寫for迴圈就不要寫while迴圈,因為while迴圈裡的index一旦改變,就要重新判斷一次,否則會導致indexOutOfBoundary!!!
//儘量寫for迴圈!!!
public static int subarraySum(int[] nums, int k) { if (nums.length == 0) return 0; int left = 0; int right = 0; int sum = nums[0]; int res = 0; while (right < nums.length) { if (sum >= k) { if (sum == k) res++; sum = sum - nums[left]; left++; if (left > right) { right = left; if (right == nums.length) break; sum = sum + nums[left]; } } else { right++; if (right == nums.length) break; sum = sum + nums[right]; } } return res; }
Lin主任的寫法(用了for迴圈):
private static int subarraySum(int[] n, int t ) { int re = 0; int l = 0; int now = 0; for(int r = 0; r < n.length; r++) { now += n[r]; while(now >= t && l < r) { if(now == t)re++; now -= n[l]; l++; } if(now == t)re++; } return re; }
解法二:只是正數的話,HashSet就足夠了。
public int subarraySum(int[] nums, int k) {
if (nums.length == 0 || k<= 0) return 0;
HashSet<Integer> set = new HashSet<>();
int sum = 0;
set.add(0);
int res = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
set.add(sum);
if (set.contains(sum - k)) {
res++;
}
}
return res;
}
Follow up 1: 如果可以有負數和0
//需要用HashMap來存sum值的個數,因為有了負數和0會導致當前sum值和前面一樣。
public int subarraySum(int[] nums, int k) {
if (nums.length == 0) return 0;
HashMap<Integer, Integer> set = new HashMap<>();
int sum = 0;
set.put(0, 1);
int res = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (set.containsKey(sum - k)) {
res = res + set.get(sum - k);
}
if (set.containsKey(sum)) {
set.put(sum, set.get(sum) + 1);
} else {
set.put(sum, 1);
}
}
return res;
}
Follow up 2: 返回最大長度
//由於需要返回最大長度,因此我們需要儲存index, 所以hashmap裡的value不存個數,而是存一個list of integer, 把所有的index存進來,這樣遇到符合的,返回list裡的第一個即可,此方法也可用於返回所有符合要求的subarray.
//注意按照定義來寫型別,
public int subarraySum(int[] nums, int k) {
if (nums.length == 0) return 0;
HashMap<Integer, List<Integer>> set = new HashMap<>();
int sum = 0;
List<Integer> list = new ArrayList<>();
list.add(-1);
set.put(0, list);
int res = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (set.containsKey(sum - k)) {
res = Math.max(res, i - set.get(sum-k).get(0));
}
if (set.containsKey(sum)) {
set.get(sum).add(i);
} else {
List<Integer> list = new ArrayList<>();
list.add(i);
set.put(sum, list);
}
}
return res;
}
以下這種方法也行,只需要存第一個integer就夠了
public int maxSubArrayLen(int[] n, int k) {
Map<Integer, Integer> m = new HashMap<>();
m.put(0, -1);
int sum = 0;
int max = 0;
for (int i = 0; i < n.length; i++) {
sum+=n[i];
if(m.containsKey(sum-k) && (i - m.get(sum-k))>max) max = i - m.get(sum-k);
if(!m.containsKey(sum))m.put(sum, i);
}
return max;
}