專欄:50多種數據結構徹底征服

專欄:50多種經典圖論算法全部掌握

搞不明白公司刷KPI的目的是什么?這玩意能提高公司的利潤嗎?還是給hr練練手?我記得在2019年找工作的時候也遇到過一次,路程一個多小時,面了兩輪問的我都回答上來了,我感覺我回答的是無可挑剔,結果他又看了簡歷說了句:我們不需要這么長工作經驗的,想招個一兩年的,一句話把我打發(fā)走了。

走在路上越想越不對,簡歷上明明寫的有工作時間,如果不需要那么長工作經驗,為什么還要叫我過來面試,當時真想把簡歷砸在他臉上。但是又感覺比那些讓你回去等通知的要真誠一些,因為讓你回去等通知,你不確定到底是自己能力不行還是來刷KPI的。但不管怎么說,讓人過來刷KPI的真的讓人很反感,不知道這么做能給公司帶來什么?

打開網易新聞 查看精彩圖片
打開網易新聞 查看精彩圖片
打開網易新聞 查看精彩圖片

--------------下面是今天的算法題--------------

來看下今天的算法題,這題是LeetCode的第1289題:下降路徑最小和 II,難度是困難。

給你一個 n x n 整數矩陣 grid ,請你返回非零偏移下降路徑數字和的最小值。

非零偏移下降路徑定義為:從 grid 數組中的每一行選擇一個數字,且按順序選出來的數字中,相鄰數字不在原數組的同一列。

示例1:

打開網易新聞 查看精彩圖片

輸入:grid = [[1,2,3],[4,5,6],[7,8,9]] 輸出:13 解釋: 所有非零偏移下降路徑包括: [1,5,9], [1,5,7], [1,6,7], [1,6,8], [2,4,8], [2,4,9], [2,6,7], [2,6,8], [3,4,8], [3,4,9], [3,5,7], [3,5,9] 下降路徑中數字和最小的是 [1,5,7] ,所以答案是 13 。

  • n == grid.length == grid[i].length

  • 1 <= n <= 200

  • -99 <= grid[i][j] <= 99

問題分析

這題說的是從二維數組的第一行開始,每行選擇一個數字,一直到最后一行,問選擇的數字最小和是多少,并且在相鄰的兩行中,選擇的數字不能在同一列,比如說第 i 行選擇了grid[i][j],那么下一行就不能選擇grid[i+1][j]。

這題是一道典型的動態(tài)規(guī)劃問題,我們定義dp[i][j]表示從第一行開始一直到第 i 行,且第 i 行選擇的是grid[i][j],所選擇的最小數字和。

當上面一行選擇數字grid[i-1][j]的時候,那么當前行可以選擇除grid[i][j]以外的任何數字,所以 dp[i][j] = min(dp[i - 1][k] + grid[i][j]);其中 k 是枚舉上一行除了第 j 列的所有數字。

對于第一行由于上面沒有數字,所以第一行可以選擇任何數字,也就是: dp[0][i] = grid[0][i];最終答案是取最后一行dp[n-1][j]的最小,其中0<=j

JAVA:

public int minFallingPathSum(int[][] grid) {     int n = grid.length;     // dp[i][j]表示從最上面一行到grid[i][j]得到的路徑最小和。     int[][] dp = newint[n][n];     // 求最小值,默認先給一個最大值。     for (int i = 0; i < n; i++)         Arrays.fill(dp[i], Integer.MAX_VALUE);     // 第一行沒法從上面下來,直接初始化。     for (int i = 0; i < n; i++)         dp[0][i] = grid[0][i];     for (int i = 1; i < n; i++) {         for (int j = 0; j < n; j++) {             // 從上一行的第 k 列到dp[i][j]。             for (int k = 0; k < n; k++) {                 if (j == k)// 當前行不能和上一行選擇同一列。                     continue;                 dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + grid[i][j]);             }         }     }     // 取最小面一行的最小值。     int ans = Integer.MAX_VALUE;     for (int j = 0; j < n; j++)         ans = Math.min(ans, dp[n - 1][j]);     return ans; }

C++:

public:     int minFallingPathSum(vector

 > &grid) {         int n = grid.size();         // dp[i][j]表示從最上面一行到grid[i][j]得到的路徑最小和。         vector

 > dp(n, vector

 (n, INT_MAX));         // 第一行沒法從上面下來,直接初始化。         for (int i = 0; i < n; i++)             dp[0][i] = grid[0][i];         for (int i = 1; i < n; i++) {             for (int j = 0; j < n; j++) {                 // 從上一行的第 k 列到dp[i][j]。                 for (int k = 0; k < n; k++) {                     if (j == k)// 當前行不能和上一行選擇同一列。                         continue;                     dp[i][j] = min(dp[i][j], dp[i - 1][k] + grid[i][j]);                 }             }         }         // 取最小面一行的最小值。         int ans = INT_MAX;         for (int j = 0; j < n; j++)             ans = min(ans, dp[n - 1][j]);         return ans;     }


筆者簡介

博哥,真名:王一博,畢業(yè)十多年, 作者,專注于 數據結構和算法 的講解,在全球30多個算法網站中累計做題2000多道,在公眾號中寫算法題解800多題,對算法題有自己獨特的解題思路和解題技巧,喜歡的可以給個關注,也可以 下載我整理的1000多頁的PDF算法文檔 。