第4章 遞推法

4.1 遞推法概述

設計思想
遞推法(Recurrence Method)通過已知的初始條件和遞推關系,逐步推導出問題的最終結果,常用于序列計算和分階段問題求解。


示例:猴子和桃子問題

題目描述
猴子每天吃掉剩余桃子的一半再多吃一個,第 10 天只剩 1 個桃子,問最初有多少個桃子?

思路

  • 設 a[n] 為第 n 天結束后剩余的桃子數;

  • 已知 a[10] = 1;

  • 從后向前有遞推關系:

    a[n] = (a[n+1] + 1) × 2
    

代碼實現

// MonkeyPeach:計算第1天最初的桃子數
int MonkeyPeach(int days) {// days 表示總共天數,本題為 10int peaches = 1;           // 從第 days-1 天開始倒推到第 1 天for (int day = days - 1; day >= 1; day--) {// 根據遞推關系 a[n] = (a[n+1] + 1) * 2// peaches 此時保存 a[n+1],更新后即為 a[n]peaches = (peaches + 1) * 2;}return peaches;            
}

整體解釋
我們先假設最后一天剩余 1 個桃子,然后按照“后一天的桃子數加 1 再乘 2”這個公式,依次向前推算,每一步都將當前天的剩余數計算出來,循環結束后 peaches 即為第 1 天最初的桃子數。


4.2 數學序列中的遞推法

4.2.1 斐波那契數列

題目描述
兔子繁殖問題:第 1、2 個月各有 1 對兔子,從第 3 個月起每月新增的兔子對數等于前兩個月兔子對數之和,求第 n 個月的兔子對數。

遞推關系

f(1) = 1,  f(2) = 1
f(n) = f(n-1) + f(n-2),  n ≥ 3

代碼實現

// Fibonacci:計算第 n 個月的兔子對數
int Fibonacci(int n) {// 前兩個月的兔子對數均為 1if (n <= 2) return 1;int prev = 1;   // f(i-2)int curr = 1;   // f(i-1)int next;       // f(i)// 從第 3 個月開始循環for (int i = 3; i <= n; i++) {next = prev + curr;   // 應用 f(i) = f(i-1) + f(i-2)prev = curr;          // 將 f(i-1) 賦值給 prevcurr = next;          // 將 f(i) 賦值給 curr}return curr;  // 返回 f(n)
}

整體解釋
我們只記錄前兩項 prevcurr,每次計算新的一項 next,然后滾動更新這兩個變量,最后 curr 存儲的就是第 n 個月的兔子對數。此方法空間復雜度 O(1),時間復雜度 O(n)。


4.2.2 卡塔蘭數

題目描述
凸 n 邊形劃分成三角形的不同方式數,第 n 個卡塔蘭數 C(n) 滿足:

C(0) = 1
C(n) = ∑_{i=0}^{n-1} C(i) × C(n-1-i),  n ≥ 1

代碼實現

// Catalan:計算第 n 個卡塔蘭數
int Catalan(int n) {// 分配數組存儲 0...n 的 C 值int C[n+1];C[0] = 1;  // C(0) = 1// 依次計算 C(1) 到 C(n)for (int i = 1; i <= n; i++) {C[i] = 0;// 按定義累加for (int k = 0; k < i; k++) {C[i] += C[k] * C[i - 1 - k];}}return C[n];
}

整體解釋
使用數組 C[] 自底向上存儲卡塔蘭數,通過兩層循環,外層決定要計算的下標 i,內層按公式累加前面各項乘積,最終 C[n] 即為答案。時間復雜度 O(n2),空間復雜度 O(n)。


4.3 組合問題中的遞推法

4.3.1 錯排問題

題目描述
有 n 封信和 n 個信封,要求沒有信件放入正確的信封,求錯排方案數 D(n),遞推關系:

D(1) = 0
D(2) = 1
D(n) = (n - 1) × (D(n-1) + D(n-2)),  n ≥ 3

代碼實現

// Derangement:計算錯排數 D(n)
int Derangement(int n) {if (n == 1) return 0;  // D(1) = 0if (n == 2) return 1;  // D(2) = 1int dn_2 = 0;  // D(n-2)int dn_1 = 1;  // D(n-1)int dn;        // D(n)// 從 n=3 開始迭代for (int i = 3; i <= n; i++) {dn = (i - 1) * (dn_1 + dn_2);dn_2 = dn_1;  // 滾動更新 D(n-2)dn_1 = dn;    // 滾動更新 D(n-1)}return dn;      // 返回 D(n)
}

整體解釋
只需保留前兩項 dn_2dn_1,用遞推公式計算當前項 dn,再向后滾動即可,空間復雜度 O(1),時間復雜度 O(n)。


4.3.2 旋轉萬花筒

題目描述
起始有 4 個閃光點,每次旋轉在每個分支末端增加 2 個閃光點,問 n 次旋轉后總閃光點數。

代碼實現

// Kale:計算旋轉 n 次后的閃光點總數
int Kale(int n) {int lamps = 4;      // 初始閃光點數int addLamp = 2;    // 每個分支基礎新增數for (int i = 1; i <= n; i++) {// 本次新增數量是上次的兩倍addLamp *= 2;// 累加到總閃光點數lamps += addLamp;}return lamps;
}

整體解釋
變量 addLamp 跟蹤每次新增的閃光點數,每次翻倍后累加到 lamps,循環結束后 lamps 為旋轉 n 次的總數。時間復雜度 O(n)。


4.4 拓展與演練

4.4.1 整數拆分(2 的冪次劃分)

題目描述
將正整數 n 拆分為若干 2 的冪次之和,求拆分方案數 d(n),遞推關系:

d(1) = 1  
d(2) = 2  
若 i 為奇數: d(i) = d(i - 1)  
否則:      d(i) = d(i - 1) + d(i / 2)

代碼實現

// PowerSplit:計算 2 的冪次拆分方案數
int PowerSplit(int n) {int d[n + 1];   // 存儲從 1 到 n 的方案數d[1] = 1;       // d(1) = 1d[2] = 2;       // d(2) = 2for (int i = 3; i <= n; i++) {if (i % 2 != 0) {// 奇數只能繼承前一個的方案d[i] = d[i - 1];} else {// 偶數可在繼承前一個方案基礎上,加上包含 i/2 的拆分d[i] = d[i - 1] + d[i / 2];}}return d[n];
}

整體解釋
用一維數組 d[] 自底向上記錄每個 i 的方案數,遇到奇數直接復制,偶數則累加前一項和 i/2 的方案即可。時間復雜度 O(n),空間 O(n)。


4.4.2 捕魚問題

題目描述
5 人輪流捕魚,每人將看到的魚分成 5 份,丟棄 1 條并帶走 1 份,其余留給下一人,直到最后一人也按此規則操作,求最少的初始魚數及每人捕魚時看到的魚數。

思路
從最小可能的初始魚數開始嘗試,依次驗證每個人都能整除且滿足規則。

代碼實現

// GetFish:計算最少的初始魚數
int GetFish(int nPeople) {int fish[5];         // fish[i] 記錄第 i+1 個人見到的魚數fish[0] = 1;         // 從最少 1 條開始嘗試while (1) {fish[0]++;       // 逐次增加初始魚數bool valid = true;// 驗證每個人是否都能按規則操作for (int i = 1; i < nPeople; i++) {// (看見數 - 1) 必須能被 5 整除if ((fish[i - 1] - 1) % 5 != 0) {valid = false;break;}// 每人帶走1份,留給下一個的人 = (fish[i-1]-1)/5*4fish[i] = (fish[i - 1] - 1) / 5 * 4;}if (valid) break;  // 全部滿足則結束循環}return fish[0];
}

整體解釋
數組 fish[] 存儲每個人見到的魚數,從第一個人開始試探最小初始值,每次嘗試后向下驗證,若所有人都滿足“(見到數-1) 能被 5 整除”,則該初始值即為答案。時間復雜度較高,但能夠找到最小解。

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

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

相關文章

可視化魔法指南

?? ECharts數據可視化魔法指南 ?? ECharts:數據的藝術畫筆 #mermaid-svg-ARwFHUrXBJ03Gpo9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ARwFHUrXBJ03Gpo9 .error-icon{fill:#552222;}#mermaid-svg-ARwFHUr…

SpringBoot學生宿舍管理系統開發實現

概述 一款基于SpringBoot框架開發的學生宿舍管理系統完整項目&#xff0c;該系統包含管理員、學生、宿管員和維修員四大角色模塊&#xff0c;功能完善&#xff0c;非常適合作為設計或二次開發的基礎項目。 主要內容 5.1 管理員功能模塊 管理員登錄界面采用驗證碼驗證機制&a…

同步 / 異步、阻塞 / 非阻塞

前言 同步異步&#xff0c;在計算機科學中是一個非常重要的概念。作為一位軟件開發工程師&#xff0c;我們每天都在和同步和異步打交道。 同步 同步-阻塞&#xff0c;顧名思義&#xff0c;就是同步和阻塞。調用方法后&#xff0c;必須等到結果返回&#xff0c;才能繼續執行別…

AOP封裝進行批量的數據查詢并填充

在我們日常的項目開發中&#xff0c;我們經常會遇到這樣的問題。我們有一張用戶表&#xff0c;用戶表中有用戶ID和用戶名稱。我們其他表中會記錄我們當前操作人的ID&#xff0c;一般&#xff0c;我們會記錄一個創建人ID和修改人ID。那么&#xff0c;這個時候問題來了&#xff0…

Java學習手冊:數據庫事務相關知識

一、事務的概念與特性 概念 &#xff1a;事務是數據庫中一系列操作的集合&#xff0c;這些操作要么全部成功&#xff0c;要么全部失敗&#xff0c;是一個不可分割的工作單位。例如&#xff0c;在銀行轉賬系統中&#xff0c;從一個賬戶扣款和向另一個賬戶存款這兩個操作必須作為…

java復雜度,包裝類,泛型解析

如何衡量代碼的好壞&#xff1f; 評價代碼的好壞我們使用算法效率來判斷&#xff0c;而算法效率分兩種&#xff1a; 算法效率&#xff1a; 第一種是時間效率&#xff0c;第二種是空間效率&#xff0c;時間效率被稱為時間復雜度&#xff0c;?空間效率被稱作空間復雜度。 時間…

基于 SpringBoot + Vue 的校園管理系統設計與實現

一、項目簡介 本系統以校園組織管理為主線&#xff0c;結合用戶權限分離機制與模塊化設計&#xff0c;實現對“單位類別、單位、通知推送、投票信息、用戶回復”等內容的全流程管理&#xff0c;廣泛適用于教育局、高校及下屬組織的信息管理工作。 &#x1f3af; 項目亮點&…

iOS藍牙技術實現及優化

以下是針對2025年iOS藍牙技術實現的核心技術要點的深度解析&#xff0c;結合當前iOS 18&#xff08;推測版本&#xff09;的最新特性與開發實踐&#xff0c;分模塊結構化呈現&#xff1a; 一、硬件與協議層適配 BLE 5.3 支持 iOS 18默認支持藍牙5.3協議&#xff0c;需注意&…

Qt 中實現觀察者模式(Observer Pattern)

在 Qt 中實現**觀察者模式(Observer Pattern)通常利用其內置的信號與槽(Signals & Slots)**機制,這是最符合 Qt 設計哲學的方式。以下是詳細實現方法和關鍵點: —### 1. 觀察者模式的核心思想- Subject(被觀察者):維護一個觀察者列表,在狀態變化時通知觀察者。- …

寫程序,統計兩會政府工作報告熱詞頻率,并生成詞云

import jieba from collections import Counter from wordcloud import WordCloud import matplotlib.pyplot as pltdef generate_wordcloud():try:# 讀取文本文件with open(E:\\桌面\\s.txt, r, encodingutf-8) as file:text file.read()# 中文分詞words jieba.lcut(text)# …

【Science Advances】普林斯頓大學利用非相干光打造可重構納米光子神經網絡

(導讀 ) 人工智能對計算性能需求劇增&#xff0c;電子微處理器發展受功耗限制。光學計算有望解決這些問題&#xff0c;光學神經網絡&#xff08;ONNs&#xff09;成為研究熱點&#xff0c;但現有 ONNs 因設計缺陷&#xff0c;在圖像分類任務中精度遠低于現代電子神經網絡&#…

gin + es 實踐 01

項目結構說明 目錄結構概覽 Go-ES 項目采用領域驅動設計&#xff08;DDD&#xff09;架構&#xff0c;目錄結構清晰&#xff0c;各層次職責分明。以下是項目的主要目錄結構&#xff1a; go-es/ ├── cmd/ # 應用程序入口 │ └── api/ …

如何構建直播美顏SDK?從美顏API調用邏輯到GPU優化實戰

隨著短視頻和直播行業的爆發&#xff0c;美顏SDK已成為各大直播平臺的“標配”。從基礎的磨皮、美白&#xff0c;到如今的AI濾鏡、虛擬形象&#xff0c;這些功能的背后都離不開高效的美顏SDK支持。那么&#xff0c;如何構建一款性能優越、體驗流暢的直播美顏SDK呢&#xff1f;本…

高組裝導軌的特點

高組裝導軌通常是四列式單圓弧齒形接觸直線導軌&#xff0c;具有整合化的結構設計&#xff0c;適用于重負荷和精密應用。與其它直線導軌高組裝導軌提升了負荷與剛性能力&#xff0c;具備四方向等負載特色和自動調心功能&#xff0c;能夠吸收安裝面的裝配誤差&#xff0c;達到高…

2025-05-07-FFmpeg視頻裁剪(尺寸調整,畫面比例不變)

原比例如圖 原比例如圖裁剪后的比例 代碼&#xff1a; 方法一&#xff1a;極速 ffmpeg -i input.mp4 -vf "crop1080:750:0:345" -c:v libx264 -preset ultrafast -c:a copy output.mp4關鍵參數說明&#xff1a; vf “crop寬:高?y”&#xff1a;定義裁剪區域。 …

一個.Net開源的協作辦公套件,包括文檔、表格、演示文稿和表單

從零學習構建一個完整的系統 推薦一個開源的文檔協作辦公套件&#xff0c;可以很好的滿足團隊對方便、高效、安全的方式來處理文檔工作&#xff0c;促進團隊協作和信息共享。 項目簡介 ONLYOFFICE 是一個開源的辦公套件&#xff0c;包括文檔、表格、演示文稿和表單等應用程序…

虛幻基礎:硬件輸入

文章目錄 triggered&#xff1a;按下一直觸發 等于tickcompleted&#xff1a;必須等到triggered結束后 才觸發松下triggered結束 默認按鍵觸發順序按下&#xff1a;觸發兩個先 Started后 Triggered 松開Completed 觸發器&#xff1a;用于修改triggered 觸發和結束驅動閾值&…

Python中的global與nonlocal關鍵字詳解

一、前言 在Python編程中&#xff0c;變量作用域是一個非常重要的概念。對于初學者來說&#xff0c;經常會遇到在函數內部無法修改外部變量的問題。這時候&#xff0c;global和nonlocal關鍵字就能派上用場了。本文將詳細介紹這兩個關鍵字的用法、區別以及適用場景&#xff0c;…

vue-qr生成的二維碼增加下載功能

大家好&#xff01;今天給大家分享一個超實用的前端小技巧——如何在 Vue 項目中生成二維碼并實現下載功能。這個功能在分享鏈接、活動推廣等場景特別有用&#xff0c;一起來學習吧&#xff01; &#x1f50d; 功能預覽 使用 vue-qr 生成美觀二維碼點擊按鈕即可下載 PNG 格式的…

嵌入式C進階路線指南

嵌入式是工科&#xff0c;工科講究實踐。說的再多、懂得再多&#xff0c;不能做出實際的東西&#xff0c;是沒有意義的。學習嵌入式的核心原則之一就是多動手寫代碼。另外還有一個原則就是&#xff1a;從淺到深學習。接下來的內容將貫徹這兩個原則。最后強調一點&#xff0c;各…