[Lc] 最長公共子序列 | Fenwick Tree(樹狀數組):處理動態前綴和

目錄

LCR 095. 最長公共子序列

題解

Fenwick Tree(樹狀數組):處理動態前綴和

一、問題背景:當傳統方法遇到瓶頸

二、Fenwick Tree核心設計

2.1 二進制索引的魔法

2.2 關鍵操作解析

更新操作(O(log n))

查詢操作(O(log n))

三、實現細節精要

3.1 初始化優化

3.2 空間壓縮技巧

四、性能對比分析

五、進階應用場景

六、實現注意事項

七、與其他數據結構的配合

延伸閱讀


LCR 095. 最長公共子序列

給定兩個字符串 text1text2,返回這兩個字符串的最長 公共子序列 的長度。如果不存在 公共子序列 ,返回 0

一個字符串的 子序列 是指這樣一個新的字符串:它是由原字符串在不改變字符的相對順序的情況下刪除某些字符(也可以不刪除任何字符)后組成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

兩個字符串的 公共子序列 是這兩個字符串所共同擁有的子序列。

示例 1:

輸入:text1 = "abcde", text2 = "ace" 
輸出:3  
解釋:最長公共子序列是 "ace" ,它的長度為 3 。

題解

兩個字符串可能存在多個公共子序列,題目要求計算最長公共子序列的長度,因此可以考慮使用動態規劃來解決。

二維DP數組

  • 用函數 f(i, j) 表示字符串 s1 中下標從 0 開始到 i 的子字符串 s1[0...i] 和字符串 s2 中下標從 0 開始到 j 的子字符串 s2[0...j] 的最長公共子序列的長度。
  • 對于 f(i, j),如果 s1[i] == s2[j],那么相當于在 s1[0...i - 1] 和 s2[0...j - 1] 的最長公共子序列的后面添加一個公共字符,也就是 f(i, j) = f(i - 1, j - 1) + 1。
  • 如果 s1[i] != s2[j],那么這兩個字符不可能出現在 s1[0...i] 和 s2[0...j] 的公共子序列中。
  • 此時 s1[0...i] 和 s2[0...j] 的最長公共子序列是s1[0...i - 1] 和 s2[0...j] 的最長公共子序列和s1[0...i] 和 s2[0...j - 1] 的最長公共子序列中的較大值,即 f(i, j) = max(f(i - 1, j), f(i, j - 1))。 (子序列的特性,決定了可以這么寫
  • 所以轉移狀態方程為

因為狀態方程有兩個變量,所以需要使用二維矩陣保存。同時上述方程會出現 i 或者 j 出現 -1 的情況,代表出現 -1 下標的字符串的子串目前是空的,那么就不會有公共子序列,所以 f(i, -1) = f(-1, j) = 0。

以 "abcde" 和 "badfe" 為例子,二維狀態矩陣如下圖

一開始先完成 f(i, -1) = f(-1, j) = 0 初始化,之后二維矩陣按照從左往右逐行向下遍歷填充。

  • 推薦使用逐行而不是逐列,雖然不影響算法,但是考慮到二維數組本身是按照一維數組存儲以及計算機緩存的運行機制,按照逐行遍歷的方式效率更高點。
  • 完整的代碼如下,若 s1 和 s2 的長度分別為 m 和 n,那么時間復雜度為 O(mn),空間復雜度為 O(mn)。
class Solution {
public:int longestCommonSubsequence(string text1, string text2) {int n1 = text1.size();int n2 = text2.size();vector<vector<int>> dp(n1 + 1, vector<int>(n2 + 1));for (int i = 0; i < n1; ++i) {for (int j = 0; j < n2; ++j) {if (text1[i] == text2[j]) {dp[i + 1][j + 1] = dp[i][j] + 1;} else {dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);}}} return dp[n1][n2];}
};
  • 當前==,就f(i - 1, j - 1) + 1
  • 當前不等,就存遍歷過的最大max(f(i - 1, j), f(i, j - 1))

遍歷

將 i==0 和 i==3 的情況來查看一下

2179. 統計數組中好三元組數目

給你兩個下標從 0 開始且長度為 n 的整數數組 nums1nums2 ,兩者都是 [0, 1, ..., n - 1]排列

好三元組 指的是 3互不相同 的值,且它們在數組 nums1nums2 中出現順序保持一致。換句話說,如果我們將 pos1v 記為值 vnums1 中出現的位置,pos2v 為值 vnums2 中的位置,那么一個好三元組定義為 0 <= x, y, z <= n - 1 ,且 pos1x < pos1y < pos1zpos2x < pos2y < pos2z 都成立的 (x, y, z)

請你返回好三元組的 總數目

示例 1:

輸入:nums1 = [2,0,1,3], nums2 = [0,1,2,3]
輸出:1
解釋:
總共有 4 個三元組 (x,y,z) 滿足 pos1x < pos1y < pos1z ,分別是 (2,0,1) ,(2,0,3) ,(2,1,3) 和 (0,1,3) 。
這些三元組中,只有 (0,1,3) 滿足 pos2x < pos2y < pos2z 。所以只有 1 個好三元組。

示例 2:

輸入:nums1 = [4,0,1,3,2], nums2 = [4,1,0,2,3]
輸出:4
解釋:總共有 4 個好三元組 (4,0,3) ,(4,0,2) ,(4,1,3) 和 (4,1,2) 。

下標比較相當于是一種映射規則。現在我在這種映射規則上再施加一種映射規則,讓在nums1中滿足下標遞增這種性質映射為鍵值遞增這種性質。

同樣的對nums2施加這種規則,下標遞增也應該映射為鍵值遞增。有一點點往這方面想,不看題解根本無法完全想出來。

template<typename T>
class FenwickTree {vector<T> tree;public:// 使用下標 1 到 nFenwickTree(int n) : tree(n + 1) {}// a[i] 增加 val// 1 <= i <= nvoid update(int i, T val) {for (; i < tree.size(); i += i & -i) {tree[i] += val;}}// 求前綴和 a[1] + ... + a[i]// 1 <= i <= nT pre(int i) const {T res = 0;for (; i > 0; i &= i - 1) {res += tree[i];}return res;}
};class Solution {
public:long long goodTriplets(vector<int>& nums1, vector<int>& nums2) {int n = nums1.size();vector<int> p(n);for (int i = 0; i < n; i++) {p[nums1[i]] = i;}long long ans = 0;FenwickTree<int> t(n);for (int i = 0; i < n - 1; i++) {int y = p[nums2[i]];int less = t.pre(y);ans += (long) less * (n - 1 - y - (i - less));t.update(y + 1, 1);}return ans;}
};

Fenwick Tree(樹狀數組):處理動態前綴和

一、問題背景:當傳統方法遇到瓶頸

在數據處理場景中,我們常需要快速計算數組的前綴和(Prefix Sum)。

傳統的前綴和數組方法雖然能在O(1)時間完成查詢,但面對頻繁更新的動態數據時,其O(n)的更新時間復雜度將成為性能瓶頸。

想象一個股票交易系統需要實時追蹤每分鐘的成交額統計,這種場景正是Fenwick Tree大顯身手的戰場。

二、Fenwick Tree核心設計

2.1 二進制索引的魔法

該數據結構的核心創新在于將數組索引的二進制表示轉化為層次結構。每個索引對應的二進制最低有效位(LSB)決定了其管理的數據范圍:

  • 索引i的LSB位置k(從1開始計數)
  • 該節點負責管理區間[i - 2^{k-1} + 1, i]的數據

2.2 關鍵操作解析

更新操作(O(log n))
def update(i, delta):while i <= n:tree[i] += deltai += i & -i  # 找到下一個父節點
查詢操作(O(log n))
def query(i):res = 0while i > 0:res += tree[i]i -= i & -i  # 剝離最低有效位return res

三、實現細節精要

3.1 初始化優化

# 最優初始化方式(時間復雜度O(n))
def build(arr):n = len(arr)tree = [0]*(n+1)for i in range(1, n+1):tree[i] += arr[i-1]j = i + (i & -i)if j <= n:tree[j] += tree[i]return tree

3.2 空間壓縮技巧

通過將原始數組映射到樹狀數組的奇數索引位置,可以節省約50%的內存空間。這種優化在嵌入式系統或處理海量數據時尤為重要。

四、性能對比分析

操作類型

前綴和數組

Fenwick Tree

初始化

O(n)

O(n)

單點更新

O(n)

O(log n)

范圍查詢

O(1)

O(log n)

空間復雜度

O(n)

O(n)

適用場景選擇指南

  • 靜態數據:優先選擇前綴和數組
  • 動態數據:必選Fenwick Tree
  • 混合操作:根據更新/查詢頻率比例決策

五、進階應用場景

  1. 逆序對統計:結合離散化技術,可在O(n log n)時間內完成
  2. 多維擴展:二維Fenwick Tree支持矩陣區域求和
  3. 頻率統計:實現高效的可變范圍頻率查詢
  4. 實時推薦系統:動態維護用戶行為熱度排名

六、實現注意事項

  1. 索引通常從1開始(避免處理0的特殊情況)
  2. 更新操作是增量式的(delta為變化量而非絕對值)
  3. 合理選擇數據存儲類型(防止整數溢出)
  4. 注意緩存友好性(順序訪問優于隨機訪問)

七、與其他數據結構的配合

  • 與線段樹結合實現區間更新/區間查詢
  • 聯合哈希表處理稀疏數據
  • 配合持久化技術實現歷史版本查詢

延伸閱讀

  • 原理解析視頻
  • 《算法導論》第15章高級數據結構
  • ACM競賽中的經典應用案例集

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77039.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77039.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77039.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python3.13.0環境安裝及python-docx庫安裝指南

1. Python環境安裝 1.1 Windows系統安裝Python 下載Python安裝包 ? 訪問Python官網 ? 點擊"Download Python 3.x.x"&#xff08;推薦使用3.8及以上版本&#xff09; 2. 運行安裝程序 ? 雙擊下載的安裝包 ? 重要&#xff1a;勾選"Add Python to environmen…

前端VUE框架理論與應用(4)

一、計算屬性 模板內的表達式非常便利,但是設計它們的初衷是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如: <div id="example">{{ message.split().reverse().join() }}</div> 在這個地方,模板不再是簡單的聲明式邏輯。你…

MySQL:存儲函數和存儲過程

系列文章目錄 1.MySQL編程基礎 2.程序控制流語句 3.存儲過程 4.游標 5.嵌入式SQL 文章目錄 系列文章目錄前言一、程序控制流語句&#xff1a;二、存儲函數&#xff1a; 1.存儲函數的特點&#xff1a;2.存儲函數的定義&#xff1a;3.調用存儲函數 三、存儲過程&#xff1a;…

基礎貪心算法集合2(10題)

目錄 1.單調遞增的數字 2.壞了的計算器 3.合并區間 4.無重疊區間 5. 用最少數量的箭引爆氣球 6.整數替換 解法1&#xff1a;模擬記憶化搜索 解法2位運算貪心 7.俄羅斯套娃信封問題 補充.堆箱子 8.可被3整除的最大和 9.距離相等的條形碼 10.重構字符串 1.單調遞增的數字…

RaabitMQ 快速入門

&#x1f389;歡迎大家觀看AUGENSTERN_dc的文章(o゜▽゜)o☆?? &#x1f389;感謝各位讀者在百忙之中抽出時間來垂閱我的文章&#xff0c;我會盡我所能向的大家分享我的知識和經驗&#x1f4d6; &#x1f389;希望我們在一篇篇的文章中能夠共同進步&#xff01;&#xff01;&…

語音識別——根據聲波能量、VAD 和 頻譜分析實時輸出文字

SenseVoiceSmall網絡結構圖 ASR(語音識別)是將音頻信息轉化為文字的技術。在實時語音識別中,一個關鍵問題是:如何決定將采集的音頻數據輸入大模型的最佳時機?固定時間間隔顯然不夠靈活,太短可能導致頻繁調用模型,太長則會延遲文字輸出。有沒有更智能的方式?答案是肯定…

AI大模型如何重塑科研范式:從“假說驅動”到“數據涌現”

??個人主頁??:慌ZHANG-CSDN博客 ????期待您的關注 ???? 一、引言:科研進入“模型共研”時代 傳統科研范式通常以“假設→實驗→驗證→理論”的方式推進,這一經典路徑建立在人類的認知能力與邏輯推理基礎上。然而,隨著數據規模的爆炸式增長與知識系統的高度復雜…

使用Python寫入JSON、XML和YAML數據到Excel文件

在當今數據驅動的技術生態中&#xff0c;JSON、XML和YAML作為主流結構化數據格式&#xff0c;因其層次化表達能力和跨平臺兼容性&#xff0c;已成為系統間數據交換的通用載體。然而&#xff0c;當需要將這類半結構化數據轉化為具備直觀可視化、動態計算和協作共享特性的載體時&…

面試題:Eureka和Nocas的區別

Eureka 與 Nacos 核心區別對比 一、功能定位與核心能力 ?維度??Eureka??Nacos??核心功能?專注服務注冊與發現&#xff0c;無配置管理功能?:ml-citation{ref“1,3” data“citationList”}集成服務注冊、發現、配置管理、動態DNS等?:ml-citation{ref“1,3” data“c…

2025年4月15日 百度一面 面經

目錄 1. 代理相關 從靜態代理到動態代理 2. cglib可以代理被final修飾的類嗎,為什么 3. JVM 體系結構 4. 垃圾回收算法 5. 什么是注解 如何使用 底層原理 6. synchronized和reentrantlock 7. 講一下你項目中 redis的分布式鎖 與java自帶的鎖有啥區別 8. post 請求和 ge…

AI改變生活

AI改變生活 人工智能&#xff08;AI&#xff09;在我們生活中的應用越來越廣泛&#xff0c;深刻地改變了我們的工作和生活方式。以下是一些AI實際應用的實例&#xff0c;以及它們如何影響我們的日常生活。 1. 智能助手 智能助手如Siri、Alexa和Google Assistant等&#xff0…

信奧賽之c++基礎(取模運算與數位分離)

?? 數字拆解大冒險——取模運算與數位分離魔法課 ?? 第一章:糖果分裝術——取模運算 ?? 分糖果游戲 7顆糖每人分3顆: 每人得到:7 / 3 = 2顆剩余糖果:7 % 3 = 1顆(%就是取模符號) 就像把糖果裝袋后剩下的零散糖粒!?? 取模運算說明書 算式比喻結果10 % 310顆糖分…

揭秘大數據 | 21、軟件定義計算

老夫先將這個小系列的前兩篇內容鏈接奉上&#xff0c;方便感興趣的朋友一氣讀之。 揭秘大數據 | 19、軟件定義的世界-CSDN博客 揭秘大數據 | 20、軟件定義數據中心-CSDN博客 今天&#xff0c;書接上文&#xff0c;開聊軟件定義計算的那些事兒&#xff01; 虛擬化是軟件定義…

FPGA-DDS技術的波形發生器

1.實驗目的 1.1掌握直接數字頻率合成&#xff08;DDS&#xff09;的基本原理及其實現方法。 1.2在DE2-115 FPGA開發板上設計一個可調頻率的正弦波和方波發生器&#xff0c;頻率范圍10Hz~5MHz&#xff0c;最小分辨率小于1kHz。 1.3使用Quartus II進行仿真&#xff0c;并通過S…

LeetCode[541]反轉字符串Ⅱ

思路&#xff1a; 題目給我們加了幾個規則&#xff0c;剩余長度小于2k&#xff0c;大于等于k就反轉k個&#xff0c;小于k就全部反轉&#xff0c;我們按照這個邏輯來就行。 第一就是大于等于k就反轉k個&#xff0c;我們for循環肯定是i2k了&#xff0c;接下來就是判斷是否大于等于…

實現定長的內存池

池化技術 所謂的池化技術&#xff0c;就是程序預先向系統申請過量的資源&#xff0c;然后自己管理起來&#xff0c;以備不時之需。這個操作的價值就是&#xff0c;如果申請與釋放資源的開銷較大&#xff0c;提前申請資源并在使用后并不釋放而是重復利用&#xff0c;能夠提高程序…

路由器原理與配置技術詳解

一、路由基礎原理 1.1 路由器的核心功能 網絡層設備&#xff1a;工作在OSI參考模型第三層&#xff0c;實現不同網絡間的互聯互通智能路徑選擇&#xff1a;基于路由表為數據包選擇最優傳輸路徑協議轉換&#xff1a;處理不同網絡接口間的協議差異&#xff08;如以太網與PPP&…

Leetcode 3518. Smallest Palindromic Rearrangement II

Leetcode 3518. Smallest Palindromic Rearrangement II 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;Leetcode 3518. Smallest Palindromic Rearrangement II 1. 解題思路 這一題是題目Leetcode 3517. Smallest Palindromic Rearrangement I的升級版本&#xff0c;其主要的…

大模型——Crawl4AI 中的數據提取策略

大模型——Crawl4AI 中的數據提取策略 在本章中,將詳細介紹在 Crawl4AI 中可用的數據提取策略。這些策略包括: LLMExtractionStrategy:用于詳細內容提取。JsonCssExtractionStrategy:使用 CSS 選擇器進行結構化數據檢索。CosineStrategy:基于余弦相似性進行有效的語義分段…

職坐標解碼互聯網行業轉型發展新動能

當前&#xff0c;互聯網行業正以前所未有的速度重塑全球產業格局。工信部最新數據顯示&#xff0c;我國互聯網企業營收連續三年保持雙位數增長&#xff0c;其中百強企業在人工智能、物聯網等領域的投入強度同比提升40%&#xff0c;展現出強勁的技術引領力。與此同時&#xff0c…