1477. Find Two Non-overlapping Sub-arrays Each With Target Sum
T: O(n)
S: O(n)
class Solution {
public int minSumOfLengths(int[] arr, int target) {
int n = arr.length;
int sum = 0;
Map<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
int best = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
sum += arr[i];
if (map.containsKey(sum - target)) {
len = Math.min(len, i - map.get(sum - target));
}
// 左邊一定會先出來, 所以 len != Integer.MAX_VALUE, 不然空有右邊一個, 沒有用
if (map.containsKey(sum + target) && len != Integer.MAX_VALUE) {
res = Math.min(res, len + map.get(sum + target) - i);
}
}
return res == Integer.MAX_VALUE ? -1 : res;
}
}
/*
0 -1. => 0 -(-1) = 1
3 0
5 1
7 2
11 3 map.get(curSum + target) = get(11+3) = get(14) = 4, 4-i = 4-3 = 1
14 4
3
[3,2,2, 4, 3] target = 3
0 3 5 7 11 14
4
cursum |
|--------|---------|--------|
pre target target
思路: 預先建構出 presum hashmap
之後 check map.get(sum - target), i - map.get(sum - target)
map.get(sum + target), map.get(sum + target) - i
這樣不會 overlap, 因為當 for (int i = 0; i < n; i++)
我們總是去看 i 之前的, 也就是 sum - target 有沒有 符合的
和看 i 之後的, 也就是 sum + target
*/
if arrays contain negative number
T: O(n)
S: O(n)
class Solution {
public int minSumOfLengths(int[] arr, int target) {
int n = arr.length;
Map<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
int sum = 0;
int[] left = new int[n];
int min = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
sum += arr[i];
if (map.containsKey(sum - target)) {
min = Math.min(min, i - map.get(sum - target));
}
left[i] = min;
map.put(sum, i);
}
System.out.println("left:"+Arrays.toString(left));
map = new HashMap<>();
map.put(0, n);
sum = 0;
int[] right = new int[n];
min = Integer.MAX_VALUE;
for (int i = n-1; i >= 0; i--) {
sum += arr[i];
if (map.containsKey(sum - target)) {
min = Math.min(min, map.get(sum - target) - i);
}
right[i] = min;
map.put(sum, i);
}
System.out.println("right:"+Arrays.toString(right));
int res = Integer.MAX_VALUE;
for (int i = 1; i < n; i++) {
if (left[i-1] != Integer.MAX_VALUE && right[i] != Integer.MAX_VALUE) {
res = Math.min(res, left[i-1] + right[i]);
}
}
return res == Integer.MAX_VALUE ? -1 : res;
}
}
/*
1. left[i] is the size of the min size subarray in arr[0, i] that sums up to target.
Is Integer.MAX_VALUE if there is no subarray that sums up to target.
2. right[i] is the size of the min size subarray in arr[i, arr.length - 1] that sums up to target.
3. for (int i = 1; i < arr.length; ++i) result = Math.min(result, left[i - 1] + right[i]);
has negative:
2 -1 0 -1 2 target 1, ans 4
0 2 1. 1 0 2
(sum, index)
0 -1
2 0
1 1 sum - target = 1-1 = 0, 1 -(-1) = 2
1 2
0 3
2 4
from end do prefix sum
2 -1 0 -1 2 target 1, ans 4
2 0 1 1 2 0
(sum, index)
0, arrlen = 5
2 arrlen-1 4
1 arrlen-2 3 => sum-target = 1 -1 = 0, map.get(0) = 5 - i = 5-3 = 2
1 arrlen-3 2
0 arrlen-4 1
2 arrlen-5 0
ex2:
[3,2,2,4,3]
3
left:[1, 1, 1, 1, 1]
right:[1, 1, 1, 1, 1]
so at last : min(left+right) = 2
no negative:
0 -1. => 0 -(-1) = 1
3 0
5 1
7 2
11 3 map.get(curSum + target) = get(11+3) = get(14) = 4, 4-i = 4-3 = 1
14 4
3
[3,2,2, 4, 3] target = 3
0 3 5 7 11 14
4
cursum |
|--------|---------|--------|
pre target target
思路: 預先建構出 presum hashmap
之後 check map.get(sum - target), i - map.get(sum - target)
map.get(sum + target), map.get(sum + target) - i
這樣不會 overlap, 因為當 for (int i = 0; i < n; i++)
我們總是去看 i 之前的, 也就是 sum - target 有沒有 符合的
和看 i 之後的, 也就是 sum + target
*/
Last updated