1477 Find Two Non-overlapping Sub-arrays Each With Target Sum
You are given an array of integers arr and an integer target.
You have to find two non-overlapping sub-arrays of arr each with a sum equal target. There can be multiple answers so you have to find an answer where the sum of the lengths of the two sub-arrays is minimum.
Return the minimum sum of the lengths of the two required sub-arrays, or return -1 if you cannot find such two sub-arrays.
Example 1:
Input: arr = [3,2,2,4,3], target = 3
Output: 2
Explanation: Only two sub-arrays have sum = 3 ([3] and [3]). The sum of their lengths is 2.
Example 2:
Input: arr = [7,3,4,7], target = 7
Output: 2
Explanation: Although we have three non-overlapping sub-arrays of sum = 7 ([7], [3,4] and [7]), but we will choose the first and third sub-arrays as the sum of their lengths is 2.
Example 3:
Input: arr = [4,3,2,6,2,3,4], target = 6
Output: -1
Explanation: We have only one sub-array of sum = 6.
这个做法是,先左到右来一遍prefixSum求min,再右到左来一遍suffixSum求min,最后从左到右过一遍,把前后加起来的min返回就好了。但一直没掌握好的138又出来了。这次好像已经懂了。就是,prefixSum可以先把位置存在值里。又或者可以像437 Path Sum III 存path的个数。每次如果在prefixSum的hashmap里,找到了现在为止的sum_so_far - target的值,证明,那个位置到到现在这个位置那一段subarray,是target的值。举个栗子:
publicintminSumOfLengths(int[] arr,int target) {if (arr ==null||arr.length==0) {return-1; }int len =arr.length;int best =Integer.MAX_VALUE;int[] left =newint[len];int sum =0;// <preSum, loc>Map<Integer,Integer> preSumMap =newHashMap<>();preSumMap.put(0,-1);for (int i =0; i < len; i++) { sum = sum + arr[i];if (preSumMap.containsKey(sum - target)) { best =Math.min(best, i -preSumMap.get(sum - target)); } left[i] = best;preSumMap.put(sum, i); } best =Integer.MAX_VALUE;int[] right =newint[len]; sum =0;// <sufSum, loc>Map<Integer,Integer> sufSumMap =newHashMap<>();sufSumMap.put(0, len);for (int i = len -1; i >=0; i--) { sum = sum + arr[i];if (sufSumMap.containsKey(sum - target)) { best =Math.min(best,sufSumMap.get(sum - target) - i); } right[i] = best;sufSumMap.put(sum, i); }int result =Integer.MAX_VALUE;for (int i =1; i < len; i++) {if (left[i -1] !=Integer.MAX_VALUE&& right[i] !=Integer.MAX_VALUE) { result =Math.min(left[i -1] + right[i], result); } }return result ==Integer.MAX_VALUE?-1: result;}