Leetcode---8.前綴和&差分篇


一、基本概念

前綴和指一個數組的某下標之前的所有數組元素的和(包含其自身),前綴和是一種重要的預處理,能夠降低算法的時間復雜度。
preSum是前綴和數組, nums是內容數組。
擁有前綴和數組后, 我們可以在O(1)的時間復雜度內求出區間和。

使用場景:
前綴和計算通常作為某種計算的預處理過程,作數據記憶以減少計算,時間復雜度為O(n)。預處理后各點的前綴和保存下來(數組或hash表),供后續計算時查詢,例如從i到j的子數組的和為 S[j]−S[i−1],即兩點前綴和之差,時間復雜度為O(1)。

1.一維前綴和

涉及連續子數組求和時,通常使用“前綴和”來解決。最簡單的一維前綴和如下:
前綴和為從第0項到第i項的和,即S[i]=A[0]+A[1]+…+A[i],計算時基於前值S[i]= S[i-1] +A[i]
某項值可以表示為相鄰前綴和之差:A[i]=S[i]−S[i−1]
從i到j的子數組的和:A[i]+…+A[j]=S[j]−S[i−1]

2.二維前綴和

二維矩陣(或二維數組)及前綴和示例如下
二維前綴和 S[i][j] = S[i-1][j] + S[i][j-1] – S[i-1][j-1] + A[i][j]
子矩陣(r1, c1)到(r2, c2)的和為:S[r2][c2] – S[r1-1][c2] – S[r2][c1-1] + S[r1-1][c1-1]

3.樹上前綴和

樹上前綴和通常分為兩種:
從根到某節點的路徑上點(或邊)的值之和,如下圖所示:
image-20201212190410230

某節點及其所有子節點(或邊)的值之和,如下下圖:
image-20201212190410230

點擊查看代碼
class NumArray {
    // 前綴和數組
    private int[] preSum;

    /* 輸入一個數組,構造前綴和 */
    public NumArray(int[] nums) {
        // preSum[0] = 0,便於計算累加和
        preSum = new int[nums.length + 1];
        // 計算 nums 的累加和
        for (int i = 1; i < preSum.length; i++) {
            preSum[i] = preSum[i - 1] + nums[i - 1];
        }
    }

    /* 查詢閉區間 [left, right] 的累加和 */
    public int sumRange(int left, int right) {
        return preSum[right + 1] - preSum[left];
    }
}

new 一個新的數組 preSum 出來,preSum[i] 記錄 nums[0..i-1] 的累加和。如果我想求索引區間 [1, 4] 內的所有元素之和,就可以通過 preSum[5] - preSum[1] 得出。這樣,sumRange 函數僅僅需要做一次減法運算,避免了每次進行 for 循環調用,最壞時間復雜度為常數 O(1)。
image-20201212190410230

4.練習題

  1. 和為K的子數組
  2. 區間子數組個數(中等)
  3. 水果成籃(中等)

二、差分

1.差分數組定義

真實數組a = {a[1]、a[2]、…、a[n]} // 各點真實數據
差分數組df = {df[1]、df[2]、…、df[n]} // 各點數據的變更值
df[i] = a[i] - a[i-1] // 差分數組各點數據為真實數據的變更值
a[i] = df[1] + df[2] …+ df[i] // 差分數組的前綴和即為真實數組
a[i] = a[i-1] + df[i] // 真實數據也可以從上一點數據+變更值求出

2.差分算法解題模板(題目中給出的往往為數據變更點)

  1. 初始化差分數組:根據數據變更點構造差分數組,常用map<int, int> (key: 變更點, value:變更值)
  2. 根據差分數組求原始數組:對差分數組求前綴和,求出的即為原始數組
  3. 根據原始數組判斷結果

使用場景:
差分算法題型特征:在一段區間內(例如時間/站點)給出數據變更點(例如上下車/占用釋放等),需要感知變更后數據值。

  1. 一維差分:主要用於對子數組(或區間)的元素整體加減固定值,特別是子數組較多時,可提高性能。
  2. 二維差分:對子矩陣元素整體進行加減處理,在子矩陣較多時,為提高性能,可以考慮用差分數組來處理。

2.練習題

1094.拼車:本題為一段區間給出數據變更的點(上車/下車點+人數),需要求出變更后的數據(人數)是否滿足(車容量),典型的差分算法特征,根據變更數據采用map構造差分數組,差分數組求前綴和還原各時間點真實數據,判斷真實人數是否滿足
1109.航班預訂統計:經典差分問題,本題與在拼車的基礎上疊加了返回值需要返回其真實數據數組,在上題基礎上僅差異在結果的處理。題型關鍵為:一段區間(城市)給出數據變更的點(預定人數),需要求出變更后的數據(各站點人數),典型的差分算法特征
253.會議室Ⅱ:題型關鍵為:一段區間(時間)給出數據變更的點(會議室預定/釋放),需要求出變更后的數據(會議室數量),典型的差分算法特征

參考鏈接:
【1】得嘞,一文把前綴和給扒的干干凈凈
【2】小而美的算法技巧:前綴和數組


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM