日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

数据结构与算法 | 记忆化搜索(Memorize Search)

發布時間:2023/11/16 windows 80 coder
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法 | 记忆化搜索(Memorize Search) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在本系列的文章中已經寫了二叉樹(Binary Tree)、深搜(DFS)與廣搜(BFS)、哈希表(Hash Table)等等,計劃接下來要寫的是動態規劃(Dynamic Programming,DP),它算得上是最靈活的一種算法。回憶筆者學習動態規劃的時候,最開始接觸的是經典的 “01背包” 問題;不過現在想起來,以“01背包問題”作為初次接觸的動態規劃算法的問題_并不友好_;花費了不少時間才慢慢感悟到動態規劃算法的核心思想。

先前的文章中涉及了不少搜索算法,在搜索算法上融入動態規劃算法思想的 記憶化搜索(Memorize Search)不妨是一個不錯的_承前啟后_的選擇。相對于 “01背包”類問題,記憶化搜索 對初學者 理解 動態規劃 更友好,也能更好的感受到其魅力所在。

記憶化搜索,所謂 “記憶” 引用 Geeksforgeeks 網站上介紹記憶搜索原文中一句話就是 “to transform the results of a function into something to remember.” 把函數的結果存儲下來作為 “記憶”。將“記憶”應用于搜索算法上,也就是搜索到有記錄了函數結果的地方,其實就不需要再進行函數計算,直接返回 “記憶” 的結果即可。

記憶化搜索是一種自頂向下(Top-Down)分析的算法,文字描述過于懸浮于理論,保持本系列文風且用算法題來看下記憶化搜索算法具體的內容。

自頂向下(Top-Down)

LeetCode 329. 矩陣中的最長遞增路徑【困難】

給定一個 m x n 整數矩陣 matrix ,找出其中 最長遞增路徑 的長度。
對于每個單元格,你可以往上,下,左,右四個方向移動。 你 不能 在 對角線 方向上移動或移動到 邊界外。(即不允許環繞)。

  • 直接順著題意進行分析,找到 “最長遞增路徑” 直接用搜索遍歷,把 matrix每個單元格的最長遞增路徑都計算下,返回其中最長的路徑。不妨就假設下有一個 search的函數能夠計算出 以當前單元格為起點的最長遞增路徑長度。遍歷過程中 的最大長度 存儲再 max 中,最后返回即可,代碼如下:
// 假設中的函數
public int search(int[][] matrix,int x,int y){
	int max;
	return max;
}

public int longestIncreasingPath(int[][] matrix) {

        int max = 0;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
            	//(i,j)格的最長遞增路徑長度 
                max = Math.max(max,search(matrix,i,j));
            }
        }
        return max;
    }
  • 問題開始關鍵點現在變成了 search 函數的實現;接著順著題意分析,可以往上,下,左,右四個方向移動.首先考慮一個方向情況,只往上方向移動且可以往上移動(上方相鄰的單元格大于當前單元格,遞增),那么此時 當前單元格的最大路徑長度就是 上方單元格的最大路徑 + 1,其中1代表當前單元格。
public int search(int[][] matrix,int x,int y){
    
	int number = matrix[x][y],up = 1;

	// 保障可以往“上”移動, x-1 沒有越邊界( x > 0 )
	// 且是 遞增的 matrix[x-1][y] > number
    if( x > 0 && matrix[x-1][y] > number ){

    	 // 遞歸調用,同類子問題,(x-1,y)格的最長遞增路徑長度 
         up += search( matrix, x-1, y );
    }

	return up;
}
  • 如此,擴展到 四個方向,最終當前單元格最大路徑就是 四個方向中取最大的返回。
public int search(int[][] matrix,int x,int y){

        int number = matrix[x][y],up = 1,down =1,left=1,right=1;

        if(x>0 && matrix[x-1][y] > number){
            up += search(matrix,x-1,y);
        }
        if(x+1<matrix.length && matrix[x+1][y] > number){
            down += search(matrix,x+1,y);
        }
        if(y+1<matrix[0].length && matrix[x][y+1] > number){
            right += search(matrix,x,y+1);
        }
        if(y>0 && matrix[x][y-1] > number){
            left += search(matrix,x,y-1);
        }

        return Math.max(Math.max(up,down),Math.max(right,left));
}
  • 實現到這里按照搜索思路的算法已經完成;不過會發現性能不高,分析過程會發現調用 search函數 時候,同樣一格位置會計算多次。此時聯系想想先前提到的 “記憶” ,把函數的結果存儲下來作為 “記憶”,也就是用 一個二維數組 cahce 緩存起來 已經計算過單元的結果。

    search 實現改為 (cache需要在 longestIncreasingPath 根據 matrx大小 new下,這里略) ,代碼如下:

public int[][] cache = null;

public int search(int[][] matrix,int x,int y){

        if(0 != cache[x][y])
            return cache[x][y];

        int number = matrix[x][y],up = 1,down =1,left=1,right=1;
        if(x>0 && matrix[x-1][y] > number){
            up += search(matrix,x-1,y);
        }
        if(x+1<matrix.length && matrix[x+1][y] > number){
            down += search(matrix,x+1,y);
        }
        if(y+1<matrix[0].length && matrix[x][y+1] > number){
            right += search(matrix,x,y+1);
        }
        if(y>0 && matrix[x][y-1] > number){
            left += search(matrix,x,y-1);
        }
        // 存儲 “記憶”
        cache[x][y] = Math.max(Math.max(up,down),Math.max(right,left));
        return cache[x][y];
}
  • 到此,已經按照記憶化搜索算法思路完成了問題的解決。

回顧下記憶化搜索解題過程,我們是從算法問題出發 -> 分析需要完成的計算(子問題)-> 進一步進行解決。這其實就是 自頂向下(Top-Down)的思考方式。

記憶化搜索 與 動態規劃

再來看"記憶",cache[x][y] 所記錄的是 x,y 這個單元格已經計算過的 最大路徑長度當前單元格 的最大路徑長度使用上、下、左、右四個方向上的單元格 最大路徑長度 來進行計算 ,使用"記憶" 其實就是在使用子問題的最優解。

	
	current_max = Max( up+1, down+1, left+1, right+1 )

另外一個角度描述,規劃決策 當前單元格的最大路徑 是根據 (上、下、左、右)相鄰四個方向上的單元格最大路徑 進行的計算。相鄰四個方向上的最大路徑(子問題最優解) 并非一開始靜態寫入下來,而是在程序運行過程中至少計算一次存儲下來,可看作 動態的計算。根據動態計算子問題最優結果來進行規劃決策當前最優結果,也就是所謂 動態規劃(Dynamic Programming)的字面意思。

可以多體會下: 解決最優化問題,根據子問題的最優結果 規劃決策 -> 當前問題最優結果 -> 進而求解最初問題。

所以有一種說法就是:記憶化搜索 是 動態規劃 自頂向下(Top-Down)分析的一種實現形式,通常用遞歸來實現。

最后總結本文

  1. 本系列文章中寫此篇 承前啟后的思考,記憶化搜索 的基本概念;
  2. 通過一道題演示 自頂向下(Top-Down)的分析,實際應用記憶化搜索解決 具體算法問題;
  3. 解讀 記憶化搜索 與 動態規劃 的關系,以及動態規劃一些概念;

下一篇咱們再一起繼續解讀 動態規劃(Dynamic Programming) ,歡迎關注 Java研究者專欄、博客、公眾號等

總結

以上是生活随笔為你收集整理的数据结构与算法 | 记忆化搜索(Memorize Search)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。