leetcode 542. 01 矩陣 --javascript DP

542. 01 矩陣

題目:

給定一個由 0 和 1 組成的矩陣 mat ,請輸出一個大小相同的矩陣,其中每個格子是 mat 中對應位置元素到最近的 0 的距離。算法

兩個相鄰元素間的距離爲 1 。數組

image.png

題解

動態規劃(Dynamic Programming, DP)

  • 動態規劃只能應用於有最優 子結構的問題。最優子結構的意思是局部最優解能決定全局最優解(對有些問題這個要求並不能徹底知足,故有時須要引入必定的近似)。markdown

  • 簡單地說,問題可以分解成子問題來解決oop

  • 通俗一點來說,動態規劃和其它遍歷算法(如深/廣度優先搜索)都是將原問題拆成多個子問題而後求解,他們之間最本質的區別是,動態規劃保存子問題的解,避免重複計算spa

  • 解決動態規劃問題的關鍵是找到狀態轉移方程,這樣咱們能夠通計算和儲存子問題的解來求解最終問題code

  • 同時,咱們也能夠對動態規劃進行空間壓縮,起到節省空間消耗的效果。orm

  • 在一些狀況下,動態規劃能夠當作是帶有狀態記錄(memoization)的優先搜索leetcode

  • 動態規劃是自下而上的,即先解決子問題,再解決父問題;get

  • 而用帶有狀態記錄的優先搜索自上而下的,即從父問題搜索到子問題,若重複搜索到同一個子問題則進行狀態記錄,防止重複計算。it

  • 若是題目需求的是最終狀態,那麼使用動態搜索比較方便;

  • 若是題目須要輸出全部的路徑,那麼使用帶有狀態記錄的優先搜索會比較方便。

回到本題目

一種辦法是使用一個 dp 數組作 memoization,使得廣

度優先搜索不會重複遍歷相同位置;另外一種更簡單的方法是,咱們從左上到右下進行一次動態搜

索,再從右下到左上進行一次動態搜索。兩次動態搜索便可完成四個方向上的查找。

coding

/**
 * @param {number[][]} mat
 * @return {number[][]}
 */
var updateMatrix = function(mat) {
   if(!mat.length) return {};
   let n = mat.length, m = mat[0].length;
   const dp = Array.from({length: n}, ()=> new Array(m).fill(m+n));
   for(let i = 0; i < n; i++) {
       for(let j = 0; j < m; j++) {
           if(mat[i][j] === 0) {
               dp[i][j] = 0
           }else {
                if(j > 0)
                  dp[i][j] = Math.min(dp[i][j], dp[i][j-1] + 1);
                if(i > 0)
                  dp[i][j] = Math.min(dp[i][j], dp[i-1][j] + 1)
           }
       }
   }
      for(let i = n-1; i >= 0; i--) {
       for(let j = m-1; j >= 0; j--) {
           if(mat[i][j]) {
                if(j < m-1)
                  dp[i][j] = Math.min(dp[i][j], dp[i][j+1] + 1);
                if(i < n-1)
                  dp[i][j] = Math.min(dp[i][j], dp[i+1][j] + 1)
           }
       }
   }
   return dp;
};
複製代碼
相關文章
相關標籤/搜索