【前綴和】B003_LC_找兩個和爲目標值且不重疊的子數組(記錄前綴和下標)

一、Problem

Given an array of integers arr and an integer target.

You have to find two non-overlapping sub-arrays of arr each with 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.

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.

Constraints:

1 <= arr.length <= 10^5
1 <= arr[i] <= 1000
1 <= target <= 10^8

二、Solution

方法一:前綴和

  • 用 map 記錄前綴和的每一項出現的位置 ii
  • Q:如果找和爲 tar 的子數組呢?
    A:如果 pre[i] - tar 在 map 的 keySet 中出現過,如果出現位置爲 ll,且當前位置爲 rr,則表明數組中存在一段長爲 rlr-l 的且和爲 tar 的子數組。
  • Q:如何判斷兩個和爲 tar 的子數組是否重疊?
    A:第二長的子數組的左端點大於大於第一小的子數組的右端點。證明:第一短的子數組一定是第一個找到,第二長的子數組一定是第二個找到。
class Solution {
    public int minSumOfLengths(int[] a, int tar) {
        int n = a.length, INF = 0x3f3f3f3f, pre[] = new int[n+1];
        Map<Integer, Integer> mp = new HashMap<>();
        mp.put(0, 0);
        for (int i = 1; i <= n; i++) {
            pre[i] = pre[i-1] + a[i-1];
            mp.put(pre[i], i);
        }
        int fir = INF, sec = INF, minR = 0;
        
        for (int r = 1; r <= n; r++) {
            int d = pre[r] - tar;
            if (mp.containsKey(d)) {
                int l = mp.get(d), len = Math.abs(r - l);
                if (len < fir) {
                    minR = r;
                    sec = fir;
                    fir = len;
                } else if (len < sec && l >= minR)
                    sec = len;
            }
        }
        return fir != INF && sec != INF ? fir+sec : -1;
    }
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章