《程式設計師程式碼面試指南》 矩陣最長遞增路徑問題——java實現
阿新 • • 發佈:2018-12-10
矩陣最長遞增路徑問題
題目描述:
給定一個整數矩陣matrix,每個位置你可以向左、右、下、上移動,找到其中最長的遞增路徑。 例如: matrix = [ [9,9,4], [6,6,8], [2,1,1] ] 返回4 最長路徑是[1, 2, 6, 9]. matrix = [ [3,4,5], [3,2,6], [2,2,1] ] 返回4 最長路徑是[ 2, 4,5, 6]
題目難度:
題目思路:
本題可用三種方法: 暴力遞迴、記憶搜尋、動態規劃
思路一: 直接暴力遞迴求解。 對於每一個位置上的數,其實有四種移動路線,即向上、下、左、右。移動時,只要保證向其他位置可移動(不越界,並保證下一個位置大於當前位置值)即可,求出從當前位置出發的最長遞增路徑。 最終比較,求出所有位置的最長遞增路徑。
程式碼實現:
public static int longest(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int max = 0;
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
max = Math.max(max, process(matrix, row, col)); //獲取總的最長遞增路徑
}
}
return max;
}
private static int process(int[][] matrix, int row, int col) { //求當前位置最長的遞增路徑
int path = 1; // 原地不動的長度
if (row > 0 && matrix[row - 1][col] > matrix[row][col]) { //向上移動時
path = Math.max(path, process(matrix, row - 1, col) + 1);
}
if (col > 0 && matrix[row][col - 1] > matrix[row][col]) { //向左移動時
path = Math.max(path, process(matrix, row, col - 1) + 1);
}
if (row < matrix.length - 1 && matrix[row + 1][col] > matrix[row][col]) { //向下移動時
path = Math.max(path, process(matrix, row + 1, col) + 1);
}
if (col < matrix[0].length - 1 && matrix[row][col + 1] > matrix[row][col]) { //向右移動時
path = Math.max(path, process(matrix, row, col + 1) + 1);
}
return path; //返回當前位置的最長遞增路徑
}
思路二: 記憶搜尋方法 由於思路一的暴力遞迴求解過程中存在大量位置重複計算問題。而記憶搜尋是採用dp矩陣記錄每一個位置是否在之前通過遞迴求解過。若已經求解過,只需要把上次的值直接拿過來即可。因此該思路建立的dp類似快取棧的思想,若該值快取過,就不需要再計算了。
程式碼實現:
public static int longestDP(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int max = 0;
int dp[][] = new int[matrix.length][matrix[0].length]; //快取矩陣
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
max = Math.max(max, processDP(matrix, dp, row, col)); //獲取總的最長遞增路徑
}
}
return max;
}
private static int processDP(int[][] matrix, int[][] dp, int row, int col) { //求當前位置最長的遞增路徑
if (dp[row][col] == 0) { //若該值沒有計算過,則計算當前最長遞增路徑
dp[row][col] = 1; // 原地不動的長度
if (row > 0 && matrix[row - 1][col] > matrix[row][col]) { //向上移動時
dp[row][col] = Math.max(dp[row][col], processDP(matrix, dp, row - 1, col) + 1);
}
if (col > 0 && matrix[row][col - 1] > matrix[row][col]) { //向左移動時
dp[row][col] = Math.max(dp[row][col], processDP(matrix, dp, row, col - 1) + 1);
}
if (row < matrix.length - 1 && matrix[row + 1][col] > matrix[row][col]) { //向下移動時
dp[row][col] = Math.max(dp[row][col], processDP(matrix, dp, row + 1, col) + 1);
}
if (col < matrix[0].length - 1 && matrix[row][col + 1] > matrix[row][col]) { //向右移動時
dp[row][col] = Math.max(dp[row][col], processDP(matrix, dp, row, col + 1) + 1);
}
}
return dp[row][col]; //返回當前位置的最長遞增路徑
}
思路三:動態規劃 採用動態規劃的思想,使得時間複雜度降到o(m*n)
程式碼實現:
public static int longestIncreasingPath(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int max = 0;
int dp[][] = new int[matrix.length][matrix[0].length]; //動歸矩陣
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
//要求當前位置的最長遞增路徑,需求當前位置往上下左右分別的最大遞增路徑。
max = Math.max(max, maxIncrease(matrix, dp, row + 1, col, matrix[row][col]) + 1); //下
max = Math.max(max, maxIncrease(matrix, dp, row - 1, col, matrix[row][col]) + 1); //上
max = Math.max(max, maxIncrease(matrix, dp, row, col + 1, matrix[row][col]) + 1); //右
max = Math.max(max, maxIncrease(matrix, dp, row, col - 1, matrix[row][col]) + 1); //左
}
}
return max;
}
private static int maxIncrease(int[][] matrix, int[][] dp, int row, int col, int pre) { //往當前方向走的最長遞增路徑
if (row < 0 || row >= matrix.length || col < 0 || col >= matrix[0].length || matrix[row][col] >= pre) {
return 0;
}
if (dp[row][col] == 0) { //當前位置沒有計算過
dp[row][col] = maxIncrease(matrix, dp, row + 1, col, matrix[row][col]) + 1;
dp[row][col] = Math.max(dp[row][col], maxIncrease(matrix, dp, row, col + 1, matrix[row][col]) + 1);
dp[row][col] = Math.max(dp[row][col], maxIncrease(matrix, dp, row - 1, col, matrix[row][col]) + 1);
dp[row][col] = Math.max(dp[row][col], maxIncrease(matrix, dp, row, col - 1, matrix[row][col]) + 1);
}
return dp[row][col];
}