➕用Python來實現 Prefix sum 前綴和

更新 發佈閱讀 1 分鐘

定義

Prefix Sum(前綴和)是一種用於計算陣列中任意區間和的高效方法

前綴和算是一種犧牲空間換取時間效能提升的策略。
這在需要頻繁查詢區間和的情況下特別有用。


一開始,初始化時花費O(n)時間,掃描每個元素累加,建立一個prefix sum table
接著,提供query介面,提供使用者查詢任意的區間和,並且能夠在O(1)得到答案


示意圖

raw-image

優點

1.提升區間和查詢效能,可以在O(1)時間內計算並且得到任意區間和。


缺點

1.需要額外花費O(n)空間來建立prefix sum table。

2.事前需要花費O(n)時間掃描每個陣列元素累加,建立prefix sum table。


Prefix Sum的class定義 與 初始化

class PrefixSum:
def __init__(self, arr):

# 建構子
self.prefix_sums = self._compute_prefix_sums(arr)

def _compute_prefix_sums(self, arr):

# 事先花費O(n)時間計算前綴和
prefix_sums = [0 for _ in range(len(arr)) ]

prefix_sums[0] = arr[0]

for i in range(1, len(arr)):
prefix_sums[i] = prefix_sums[i - 1] + arr[i]

return prefix_sums

Prefix Sum常見的操作


1.查詢區間和 range_sum(left, right)


如果left 是零,代表左邊端點是起點,直接返回self.prefix_sums[right]即可。

如果left非零,利用區間和抵銷的觀念,計算

self.prefix_sums[right] - self.prefix_sums[left-1] 得到區間和。


時間複雜度: O(1)

    def range_sum(self, left, right):

if left == 0:
return self.prefix_sums[right]

else:
return self.prefix_sums[right] - self.prefix_sums[left-1]

測試範例

raw-image

完整的Prefix sum實作和程式碼

class PrefixSum:
def __init__(self, arr):
self.prefix_sums = self._compute_prefix_sums(arr)

def _compute_prefix_sums(self, arr):
prefix_sums = [0 for _ in range(len(arr)) ]

prefix_sums[0] = arr[0]

for i in range(1, len(arr)):
prefix_sums[i] = prefix_sums[i - 1] + arr[i]

return prefix_sums

def range_sum(self, left, right):

if left == 0:
return self.prefix_sums[right]

else:
return self.prefix_sums[right] - self.prefix_sums[left-1]

def test():
# Demo
arr = [3, 4, 1, 7, 9, 1]
prefix_sum = PrefixSum(arr)
print("Input array :", arr)
print("Prefix sum :", prefix_sum.prefix_sums)
print("\nSum of range (1, 3):", prefix_sum.range_sum(1, 3))
print("Sum of range (0, 5):", prefix_sum.range_sum(0, 5))


if __name__ == '__main__':
test()

測試輸出

Input array : [3, 4, 1, 7, 9, 1]
Prefix sum : [3, 7, 8, 15, 24, 25]

Sum of range (1, 3): 12
Sum of range (0, 5): 25

結語


其實前綴和就是陣列元素的累加,而區間和就是區間元素的累加
透過事前額外的計算建表,提升run-time 區間和的查詢與計算效能


讀者可以透過紙筆追蹤演算法和程式執行邏輯,測試幾個簡單的小範例,

會有更深刻的了解和體會!


Prefix sum相關的演算法練習題與詳解


前綴和應用: 指定目標值的子陣列數目 Binary Subarrays With Sum_Leetcode #930


前綴和應用: 總和=k的子陣列有幾個 Subarray Sum Equals K_Leetcode #560


合縱連橫: 從區間和應用理解 前綴和 的本質


前綴和應用: 尋找旅途中的海拔最高點_Leetcode #1732 精選75題解析

留言
avatar-img
留言分享你的想法!
avatar-img
小松鼠的演算法樂園
96會員
427內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
2024/10/10
從Python 內建deque資料結構的角度切入, 同時了解deque 與 FIFO Queue相關的function用法。 collections.deque是一種兩端點皆可進出的雙端佇列 在兩端點高效地在O(1)常數時間內添加和刪除元素。 這使得deque非常適合實現FIFO Queue
Thumbnail
2024/10/10
從Python 內建deque資料結構的角度切入, 同時了解deque 與 FIFO Queue相關的function用法。 collections.deque是一種兩端點皆可進出的雙端佇列 在兩端點高效地在O(1)常數時間內添加和刪除元素。 這使得deque非常適合實現FIFO Queue
Thumbnail
2024/09/27
井字遊戲(OOXX)的遊戲描述 Tic Tac Toe(井字遊戲)是經典的雙人棋盤遊戲,在一個3x3的方格中進行。 每回合兩個玩家輪流選一個位置,先讓自己的符號(是 X 或 O)在 水平線、垂直線或對角線上連成一線的玩家宣告獲勝。
Thumbnail
2024/09/27
井字遊戲(OOXX)的遊戲描述 Tic Tac Toe(井字遊戲)是經典的雙人棋盤遊戲,在一個3x3的方格中進行。 每回合兩個玩家輪流選一個位置,先讓自己的符號(是 X 或 O)在 水平線、垂直線或對角線上連成一線的玩家宣告獲勝。
Thumbnail
2024/09/23
深入探討圖(Graph)的基本概念 及 最短路徑Shortest Path的尋找。 我們專注於廣度優先搜尋(BFS)演算法,以等權圖的最短路徑為例, 詳細說明如何利用BFS從起點擴散到終點,並且提供詳細的程式碼範例。 透過實作,讀者能夠更清楚理解圖論及BFS的應用,並體會水波紋擴散模型的重要性。
Thumbnail
2024/09/23
深入探討圖(Graph)的基本概念 及 最短路徑Shortest Path的尋找。 我們專注於廣度優先搜尋(BFS)演算法,以等權圖的最短路徑為例, 詳細說明如何利用BFS從起點擴散到終點,並且提供詳細的程式碼範例。 透過實作,讀者能夠更清楚理解圖論及BFS的應用,並體會水波紋擴散模型的重要性。
Thumbnail
看更多
你可能也想看
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
老是從頭重算可不是好法子,把加過的累積值存起來備用,這才符合 Prefix Sum 的精神!
Thumbnail
老是從頭重算可不是好法子,把加過的累積值存起來備用,這才符合 Prefix Sum 的精神!
Thumbnail
在學習過比較基本的DP模型 費式數列、爬樓梯、找零錢...等之後, 來看一個比較進階而且實用的DP模型,前綴和(Prefix sum), 可以再加以延伸推廣,來計算 區間和(Range Sum)。
Thumbnail
在學習過比較基本的DP模型 費式數列、爬樓梯、找零錢...等之後, 來看一個比較進階而且實用的DP模型,前綴和(Prefix sum), 可以再加以延伸推廣,來計算 區間和(Range Sum)。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News