0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

base case和備忘錄初始值怎么定?

jf_78858299 ? 來源:labuladong ? 作者:labuladong ? 2023-04-19 10:28 ? 次閱讀

很多讀者對(duì)動(dòng)態(tài)規(guī)劃問題的 base case、備忘錄初始值等問題存在疑問。

本文就專門講一講這類問題,順便聊一聊怎么通過題目的蛛絲馬跡揣測(cè)出題人的小心思,輔助我們解題。

看下力扣第 931 題「下降路徑最小和」,輸入為一個(gè)n * n的二維數(shù)組matrix,請(qǐng)你計(jì)算從第一行落到最后一行,經(jīng)過的路徑和最小為多少。

函數(shù)簽名如下:

int minFallingPathSum(int[][] matrix);

就是說你可以站在matrix的第一行的任意一個(gè)元素,需要下降到最后一行。

每次下降,可以向下、向左下、向右下三個(gè)方向移動(dòng)一格。也就是說,可以從matrix[i][j]降到matrix[i+1][j]matrix[i+1][j-1]matrix[i+1][j+1]三個(gè)位置。

請(qǐng)你計(jì)算下降的「最小路徑和」,比如說題目給了一個(gè)例子:

圖片

今天這道題也是類似的,不算是困難的題目,所以 我們借這道題來講講 base case 的返回值、備忘錄的初始值、索引越界情況的返回值如何確定 。

不過還是要通過 動(dòng)態(tài)規(guī)劃的標(biāo)準(zhǔn)套路介紹一下這道題的解題思路,首先我們可以定義一個(gè)dp數(shù)組:

int dp(int[][] matrix, int i, int j);

這個(gè)dp函數(shù)的含義如下:

從第一行(matrix[0][..])向下落,落到位置matrix[i][j]的最小路徑和為dp(matrix, i, j) 。

根據(jù)這個(gè)定義,我們可以把主函數(shù)的邏輯寫出來:

public int minFallingPathSum(int[][] matrix) {
    int n = matrix.length;
    int res = Integer.MAX_VALUE;

    // 終點(diǎn)可能在最后一行的任意一列
    for (int j = 0; j < n; j++) {
        res = Math.min(res, dp(matrix, n - 1, j));
    }

    return res;
}

因?yàn)槲覀兛赡苈涞阶詈笠恍械娜我庖涣?,所以要窮舉一下,看看落到哪一列才能得到最小的路徑和。

接下來看看dp函數(shù)如何實(shí)現(xiàn)。

對(duì)于matrix[i][j],只有可能從matrix[i-1][j], matrix[i-1][j-1], matrix[i-1][j+1]這三個(gè)位置轉(zhuǎn)移過來。

圖片

那么,只要知道到達(dá)(i-1, j), (i-1, j-1), (i-1, j+1)這三個(gè)位置的最小路徑和,加上matrix[i][j]的值,就能夠計(jì)算出來到達(dá)位置(i, j)的最小路徑和

int dp(int[][] matrix, int i, int j) {
    // 非法索引檢查
    if (i < 0 || j < 0 ||
        i >= matrix.length ||
        j >= matrix[0].length) {
        // 返回一個(gè)特殊值
        return 99999;
    }
    // base case
    if (i == 0) {
        return matrix[i][j];
    }
    // 狀態(tài)轉(zhuǎn)移
    return matrix[i][j] + min(
            dp(matrix, i - 1, j), 
            dp(matrix, i - 1, j - 1),
            dp(matrix, i - 1, j + 1)
        );
}

int min(int a, int b, int c) {
    return Math.min(a, Math.min(b, c));
}

當(dāng)然,上述代碼是暴力窮舉解法,我們可以用備忘錄的方法消除重疊子問題,完整代碼如下:

public int minFallingPathSum(int[][] matrix) {
    int n = matrix.length;
    int res = Integer.MAX_VALUE;
    // 備忘錄里的值初始化為 66666
    memo = new int[n][n];
    for (int i = 0; i < n; i++) {
        Arrays.fill(memo[i], 66666);
    }
    // 終點(diǎn)可能在 matrix[n-1] 的任意一列
    for (int j = 0; j < n; j++) {
        res = Math.min(res, dp(matrix, n - 1, j));
    }
    return res;
}

// 備忘錄
int[][] memo;

int dp(int[][] matrix, int i, int j) {
    // 1、索引合法性檢查
    if (i < 0 || j < 0 ||
        i >= matrix.length ||
        j >= matrix[0].length) {

        return 99999;
    }
    // 2、base case
    if (i == 0) {
        return matrix[0][j];
    }
    // 3、查找備忘錄,防止重復(fù)計(jì)算
    if (memo[i][j] != 66666) {
        return memo[i][j];
    }
    // 進(jìn)行狀態(tài)轉(zhuǎn)移
    memo[i][j] = matrix[i][j] + min(
            dp(matrix, i - 1, j), 
            dp(matrix, i - 1, j - 1),
            dp(matrix, i - 1, j + 1)
        );

    return memo[i][j];
}

int min(int a, int b, int c) {
    return Math.min(a, Math.min(b, c));
}

如果看過我們公眾號(hào)之前的動(dòng)態(tài)規(guī)劃系列文章,這個(gè)解題思路應(yīng)該是非常容易理解的。

那么本文對(duì)于這個(gè)dp函數(shù)仔細(xì)探討三個(gè)問題

1、對(duì)于索引的合法性檢測(cè),返回值為什么是 99999?其他的值行不行?

2、base case 為什么是i == 0?

3、備忘錄memo的初始值為什么是 66666?其他值行不行?

首先,說說 base case 為什么是i == 0,返回值為什么是matrix[0][j],這是根據(jù)dp函數(shù)的定義所決定的 。

回顧我們的dp函數(shù)定義:

從第一行(matrix[0][..])向下落,落到位置matrix[i][j]的最小路徑和為dp(matrix, i, j)。

根據(jù)這個(gè)定義,我們就是從matrix[0][j]開始下落。那如果我們想落到的目的地就是i == 0,所需的路徑和當(dāng)然就是matrix[0][j]唄。

再說說備忘錄memo的初始值為什么是 66666,這是由題目給出的數(shù)據(jù)范圍決定的 。

備忘錄memo數(shù)組的作用是什么?

就是防止重復(fù)計(jì)算,將dp(matrix, i, j)的計(jì)算結(jié)果存進(jìn)memo[i][j],遇到重復(fù)計(jì)算可以直接返回。

那么,我們必須要知道memo[i][j]到底存儲(chǔ)計(jì)算結(jié)果沒有,對(duì)吧?如果存結(jié)果了,就直接返回;沒存,就去遞歸計(jì)算。

所以,memo的初始值一定得是特殊值,和合法的答案有所區(qū)分。

我們回過頭看看題目給出的數(shù)據(jù)范圍:

matrixn * n的二維數(shù)組,其中1 <= n <= 100;對(duì)于二維數(shù)組中的元素,有-100 <= matrix[i][j] <= 100

假設(shè)matrix的大小是 100 x 100,所有元素都是 100,那么從第一行往下落,得到的路徑和就是 100 x 100 = 10000,也就是最大的合法答案。

類似的,依然假設(shè)matrix的大小是 100 x 100,所有元素是 -100,那么從第一行往下落,就得到了最小的合法答案 -100 x 100 = -10000。

也就是說,這個(gè)問題的合法結(jié)果會(huì)落在區(qū)間[-10000, 10000]中。

所以,我們memo的初始值就要避開區(qū)間[-10000, 10000],換句話說,memo的初始值只要在區(qū)間(-inf, -10001] U [10001, +inf)中就可以。

最后,說說對(duì)于不合法的索引,返回值應(yīng)該如何確定,這需要根據(jù)我們狀態(tài)轉(zhuǎn)移方程的邏輯確定

對(duì)于這道題,狀態(tài)轉(zhuǎn)移的基本邏輯如下:

int dp(int[][] matrix, int i, int j) {

    return matrix[i][j] + min(
            dp(matrix, i - 1, j), 
            dp(matrix, i - 1, j - 1),
            dp(matrix, i - 1, j + 1)
        );
}

顯然,i - 1, j - 1, j + 1這幾個(gè)運(yùn)算可能會(huì)造成索引越界,對(duì)于索引越界的dp函數(shù),應(yīng)該返回一個(gè)不可能被取到的值。

因?yàn)槲覀冋{(diào)用的是min函數(shù),最終返回的值是最小值,所以對(duì)于不合法的索引,只要dp函數(shù)返回一個(gè)永遠(yuǎn)不會(huì)被取到的最大值即可。

剛才說了,合法答案的區(qū)間是[-10000, 10000],所以我們的返回值只要大于 10000 就相當(dāng)于一個(gè)永不會(huì)取到的最大值。

換句話說,只要返回區(qū)間[10001, +inf)中的一個(gè)值,就能保證不會(huì)被取到。

至此,我們就把動(dòng)態(tài)規(guī)劃相關(guān)的三個(gè)細(xì)節(jié)問題舉例說明了。

拓展延伸一下,建議大家做題時(shí),除了題意本身,一定不要忽視題目給定的其他信息

本文舉的例子,測(cè)試用例數(shù)據(jù)范圍可以確定「什么是特殊值」,從而幫助我們將思路轉(zhuǎn)化成代碼。

除此之外,數(shù)據(jù)范圍還可以幫我們估算算法的時(shí)間/空間復(fù)雜度。

比如說,有的算法題,你只想到一個(gè)暴力求解思路,時(shí)間復(fù)雜度比較高。如果發(fā)現(xiàn)題目給定的數(shù)據(jù)量比較大,那么肯定可以說明這個(gè)求解思路有問題或者存在優(yōu)化的空間。

除了數(shù)據(jù)范圍,有時(shí)候題目還會(huì)限制我們算法的時(shí)間復(fù)雜度,這種信息其實(shí)也暗示著一些東西。

比如要求我們的算法復(fù)雜度是O(NlogN),你想想怎么才能搞出一個(gè)對(duì)數(shù)級(jí)別的復(fù)雜度呢?

肯定得用到 二分搜索或者二叉樹相關(guān)的數(shù)據(jù)結(jié)構(gòu),比如TreeMap,PriorityQueue之類的對(duì)吧。

再比如,有時(shí)候題目要求你的算法時(shí)間復(fù)雜度是O(MN),這可以聯(lián)想到什么?

可以大膽猜測(cè),常規(guī)解法是用 [回溯算法暴力窮舉,但是更好的解法是動(dòng)態(tài)規(guī)劃,而且是一個(gè)二維動(dòng)態(tài)規(guī)劃,需要一個(gè)M * N的二維dp數(shù)組,所以產(chǎn)生了這樣一個(gè)時(shí)間復(fù)雜度。

如果你早就胸有成竹了,那就當(dāng)我沒說,畢竟猜測(cè)也不一定準(zhǔn)確;但如果你本來就沒啥解題思路,那有了這些推測(cè)之后,最起碼可以給你的思路一些方向吧?

總之,多動(dòng)腦筋,不放過任何蛛絲馬跡,你不成為刷題小能手才怪。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Base
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    8715
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    417

    瀏覽量

    25949
  • 動(dòng)態(tài)規(guī)劃算法

    關(guān)注

    0

    文章

    6

    瀏覽量

    1625
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    恩智浦與Cohda無線簽署CAR 2 CAR通信聯(lián)盟“諒解備忘錄

    恩智浦半導(dǎo)體和Cohda的無線今天宣布,他們已經(jīng)簽署的CAR 2 CAR通信聯(lián)盟”諒解備忘錄”(MOU)。該備忘錄旨在確保歐洲車與車之間,或是汽車和交通基礎(chǔ)設(shè)施間,無線通訊科技技術(shù)的實(shí)施和統(tǒng)一
    發(fā)表于 04-17 10:10 ?922次閱讀

    HarmonyOS開發(fā)實(shí)例:【手機(jī)備忘錄

    基于用戶首選項(xiàng),實(shí)現(xiàn)了備忘錄新增、更新、刪除以及查找等功能。
    的頭像 發(fā)表于 04-18 21:40 ?813次閱讀
    HarmonyOS開發(fā)實(shí)例:【手機(jī)<b class='flag-5'>備忘錄</b>】

    PostgreSQL操作備忘錄

    PostgreSQL 操作備忘錄
    發(fā)表于 05-23 08:48

    UDS診斷命令備忘錄

    UDS實(shí)踐性強(qiáng),邏輯復(fù)雜,很多服務(wù)非要體驗(yàn)過一次才能理解,導(dǎo)致包括我在內(nèi)的初學(xué)者感覺晦澀難懂,不明覺厲,因此將自己的理解寫下來、整理下來,與君共勉。零、UDS診斷命令備忘錄一、簡介UDS
    發(fā)表于 08-26 16:09

    怎樣去搭建一種基于XR806的開源桌面備忘錄

    本人計(jì)劃懟一個(gè)開源桌面備忘錄/天氣預(yù)報(bào)/相冊(cè)的項(xiàng)目基于XR806,同時(shí)學(xué)習(xí)鴻蒙操作系統(tǒng)獲得暈哥贈(zèng)送的開發(fā)板和芯片,目前處于環(huán)境搭建階段看起來這個(gè)芯片玩的人比較少,目前遇到了問題,不知道如何解決,希望
    發(fā)表于 12-28 06:52

    換路定律及初始值的確定

    換路定律及初始值的確定:3.2 換路定律及初始值的確定3.2.1 換路定律通常,我們把電路中開關(guān)的接通、斷開或電路參數(shù)的突然變化等統(tǒng)稱為“換路”。我們研究的是換路后電
    發(fā)表于 05-10 00:04 ?30次下載

    全球半導(dǎo)體聯(lián)盟與中國半導(dǎo)體行業(yè)簽署合作備忘錄

    全球半導(dǎo)體聯(lián)盟與中國半導(dǎo)體行業(yè)簽署合作備忘錄 全球半導(dǎo)體聯(lián)盟(GSA)與中國半導(dǎo)體行業(yè)協(xié)會(huì)(CSIA)在蘇州聯(lián)合申明簽署合作備忘錄。此次合作將為促
    發(fā)表于 09-24 08:17 ?701次閱讀

    是德科技與中國移動(dòng)簽署諒解備忘錄

    是德科技(NYSE:KEYS)今日宣布與中國移動(dòng)通信集團(tuán)有限公司(CMCC)簽署諒解備忘錄(MoU)將全力支持 5G 終端先行者計(jì)劃的實(shí)施。
    的頭像 發(fā)表于 07-19 11:01 ?4844次閱讀

    戴姆勒與百度簽署諒解備忘錄

    7月25日,奔馳母公司戴姆勒與百度簽署諒解備忘錄,深化雙方在自動(dòng)駕駛和車聯(lián)網(wǎng)等領(lǐng)域的戰(zhàn)略合作。
    的頭像 發(fā)表于 07-28 09:53 ?2727次閱讀

    Vedanta與30家日本公司簽署諒解備忘錄

    印度Vedanta Group已與30家日本公司簽署諒解備忘錄,以開發(fā)印度半導(dǎo)體和玻璃顯示器制造生態(tài)系統(tǒng)。上周在日本東京舉行的2022年Vedanta-Avanstrate商業(yè)合作伙伴峰會(huì)上簽署了這些備忘錄,來自100多家全球公司的200多名代表出席了峰會(huì)。
    的頭像 發(fā)表于 12-15 09:12 ?979次閱讀

    設(shè)計(jì)模式:備忘錄設(shè)計(jì)模式

    備忘錄設(shè)計(jì)模式(Memento Design Pattern)是一種行為型設(shè)計(jì)模式,它的主要目的是在不破壞對(duì)象封裝性的前提下,捕捉和保存一個(gè)對(duì)象的內(nèi)部狀態(tài)
    的頭像 發(fā)表于 06-06 11:19 ?808次閱讀

    設(shè)計(jì)模式行為型:備忘錄模式

    備忘錄模式(Memento Pattern)保存一個(gè)對(duì)象的某個(gè)狀態(tài),以便在適當(dāng)?shù)臅r(shí)候恢復(fù)對(duì)象。備忘錄模式屬于行為型模式。
    的頭像 發(fā)表于 06-07 11:16 ?859次閱讀
    設(shè)計(jì)模式行為型:<b class='flag-5'>備忘錄</b>模式

    新思科技同越南政府簽署諒解備忘錄

    在越南總理范明政訪美期間,新思科技與越南國家創(chuàng)新中心(nic)簽署了關(guān)于培養(yǎng)越南集成電路設(shè)計(jì)人才的諒解備忘錄,支持nic成立芯片設(shè)計(jì)孵化中心。另外,新思科技與越南信息通訊部下屬的信息通信技術(shù)產(chǎn)業(yè)公司簽訂了支援越南半導(dǎo)體產(chǎn)業(yè)發(fā)展的諒解備忘錄。
    的頭像 發(fā)表于 09-20 10:56 ?1558次閱讀

    實(shí)踐GoF的23種設(shè)計(jì)模式:備忘錄模式

    相對(duì)于代理模式、工廠模式等設(shè)計(jì)模式,備忘錄模式(Memento)在我們?nèi)粘i_發(fā)中出鏡率并不高,除了應(yīng)用場(chǎng)景的限制之外,另一個(gè)原因,可能是備忘錄模式
    的頭像 發(fā)表于 11-25 09:05 ?549次閱讀
    實(shí)踐GoF的23種設(shè)計(jì)模式:<b class='flag-5'>備忘錄</b>模式

    蘋果iOS 18將支持語音備忘錄及數(shù)學(xué)符號(hào)顯示

    首先是語音備忘錄功能。據(jù)悉,蘋果有意在iOS 18系統(tǒng)中加入此項(xiàng)功能,使iPhone用戶能夠便捷地錄制音頻文件,并將其直接嵌入至備忘錄之中。
    的頭像 發(fā)表于 04-18 11:14 ?527次閱讀