資料結構與演算法1 字首和技巧

2021-10-11 01:39:23 字數 2767 閱讀 2461

基礎型別1  leedcode560 和為k的子陣列

給定乙個整數陣列和乙個整數 k,你需要找到該陣列中和為 k 的連續的子陣列的個數。

型別 1 :

輸入:nums = [1,1,1], k = 2

輸出: 2 , [1,1] 與 [1,1] 為兩種不同的情況。

class solution:

def subarraysum(self, nums: list[int], k: int) -> int:

sum0,sum1 = 0,0

ans = 0

// map: 字首和 -> 該字首和出現的次數

presum =

for num in nums:

sum0 += num

// 這是我們想找的字首和 num1[0..j]

sum1 = sum0 - k

// 如果前⾯有這個字首和, 則直接更新答案

if sum1 in presum:

ans += presum.get(sum1)

presum[sum0] = presum.get(sum0,0)+1 // 把字首和 nums[0..i] 加⼊並記錄出現次數

return ans

備註:

1. 這裡的乙個關鍵點就是hash表的定義,這裡是字首和:該字首和出現的次數

2. 字首和與差值k的關係:sum0 - sum1 = k

拓展:同餘原理

型別1:523. 連續的子陣列和

給定乙個包含 非負數 的陣列和乙個目標 整數 k,編寫乙個函式來判斷該陣列是否含有連續的子陣列,其大小至少為 2,且總和為 k 的倍數,即總和為 n*k,其中 n 也是乙個整數。

示例 1:

輸入:[23,2,4,6,7], k = 6

輸出:true

解釋:[2,4] 是乙個大小為 2 的子陣列,並且和為 6。

示例 2:

輸入:[23,2,6,4,7], k = 6

輸出:true

解釋:[23,2,6,4,7]是大小為 5 的子陣列,並且和為 42。

def checksubarraysum(self, nums: list[int], k: int) -> bool:

len_nums = len(nums)

sum = 0

map =

for i in range(len_nums):

sum += nums[i]

if k!= 0:

sum = sum % k

if sum in map:

if i - map.get(sum) >1:

return true

else:

item =

map.update(item)

return false

這裡要注意3點:

1. map的定義是sum%k:第i個元素(hash鍵值為sum%k),之所以這麼設計,主要是問了hash的時候方便獲得索引i,方便滿足子陣列大小大於2的要求

2.  初始值map= 的初始化原理,帶入測試用例[0,0] 0 返回值為true

3. 演算法思路(同餘原理)

設位置 j < i : 

0 到 j 的字首和 presum1 = 某常數1 * k + 餘數1

0 到 i 的字首和 presum2 = 某常數2 * k + 餘數2

當找到 餘數1 等於 餘數2時, 則 j + 1 到 i 的連續和 = presum2 - presum1 = (某常數2 - 某常數1) * k, 必為 k 的倍數, 返回true

型別2: leedcode974 和可被 k 整除的子陣列

給定乙個整數陣列 a,返回其中元素之和可被 k 整除的(連續、非空)子陣列的數目。

示例:輸入:a = [4,5,0,-2,-3,1], k = 5

輸出:7

解釋:有 7 個子陣列滿足其元素之和可被 k = 5 整除:

[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

class solution:

def subarraysdivbyk(self, a: list[int], k: int) -> int:

presum =

ans, sum = 0,0

for num in a:

sum += num

sum = sum%k

presum[sum] = presum.get(sum,0)+1

for value in presum.value(): //key 對應的value的組合

ans += int(value*(value-1)/2)

return ans

我們令 p[i] = a[0] + a[1] + ... + a[i]p[i]=a[0]+a[1]+...+a[i]。那麼每個連續子陣列的和 sum(i,j) 就可以寫成 p[j] - p[i-1]p[j]−p[i−1](其中 0 < i < j0因此我們可以考慮對陣列進行遍歷,在遍歷同時統計答案。當我們遍歷到第 i 個元素時,我們統計以 i 結尾的符合條件的子陣列個數。我們可以維護乙個以字首和模 k 的值為鍵,出現次數為值的雜湊表,在遍歷的同時進行更新。這樣在計算以 i 結尾的符合條件的子陣列個數時,根據上面的分析,答案即為[0..i−1] 中字首和模 k 也為 p[i] mod k的位置個數,即presum[p[i]modk]。

資料結構與演算法 字首和的問題

例題 給你乙個鍊錶的頭節點 head,請你編寫 反覆刪去鍊錶中由 總和 值為 0 的連續節點組成的序列,直到不存在這樣的序列為止。刪除完畢後,請你返回最終結果鍊錶的頭節點。資料案例 輸入 head 1,2,3,3,1 輸出 3,1 輸入 head 1,2,3,3,4 輸出 1,2,4 輸入 head...

資料結構與演算法(1)

演算法 資料結構 一 演算法 1.演算法的幾個特徵是什麼。2.演算法複雜性的定義。大o 小o分別表示的含義。3.遞迴演算法的定義 遞迴演算法的兩要素。4.分治演算法的思想,經典的分治演算法 全排列 二分搜尋 歸併排序 快速排序 線性時間選擇 最接近點對問題 5.動態規劃演算法解題框架,動態規劃演算法...

資料結構與演算法(1)

1 線性表 2 棧 3 佇列 4 字串 補充 遞迴 1 樹與二叉樹 2 圖 1 查詢 2 排序 編寫相關演算法 資料結構 入門問題 1.為什麼學習資料結構?1 高階程式設計的理論指導 2 提公升編碼能力 3 面試中經常被問及,看發展潛力 2.有哪些資料結構?2.11線性結構 線性表 棧 佇列 陣列 ...