package com.interview.leetcode.dp; import java.util.List; import java.util.Stack; /** * Created_By: stefanie * Date: 14-11-24 * Time: 下午9:23 */ public class MatrixDP { /** * You are climbing a stair case. It takes n steps to reach to the top. */ //Time: O(N), Space: O(1) public int climbStairs(int n) { int[] ways = new int[3]; ways[0] = 1; ways[1] = 2; for(int i = 2; i < n; i++){ ways[i%3] = ways[(i - 2)%3] + ways[(i - 1)%3]; } return ways[(n - 1)%3]; } /** * Given a grid, and some obstacles are added. * How many unique paths would there be from 0.0 to m.n? */ public int uniquePathsWithObstacles(int[][] grid) { if(grid.length == 0) return 0; int m = grid.length; int n = grid[0].length; int[][] path = new int[m][n]; path[0][0] = grid[0][0] == 1? 0 : 1; for(int i = 1; i < m; i++) path[i][0] = grid[i][0] == 1? 0 : path[i - 1][0]; for(int i = 1; i < n; i++) path[0][i] = grid[0][i] == 1? 0 : path[0][i - 1]; for(int i = 1; i < m; i++){ for(int j = 1; j < n; j++){ path[i][j] = grid[i][j] == 1? 0 : path[i - 1][j] + path[i][j - 1]; } } return path[m - 1][n - 1]; } /** * Given a triangle of int numbers. Find the min path from the top to the bottom * State: path[i][j] the path sum of j-th element from 0 layer to i-th layer * Transfer: path[i][j] = Math.min(path[i-1][j], path[i-1][j-1]) * Init: path[0][0] = element in layer 0 * Result: the min path in layer n */ public int minPathInTriangle(List<List<Integer>> triangle) { if(triangle == null || triangle.size() == 0) return 0; int layer = triangle.size(); int[] path = new int[layer]; path[0] = triangle.get(0).get(0); for(int i = 1; i < layer; i++){ List<Integer> current = triangle.get(i); for(int j = current.size() - 1; j >= 0; j--){ if(j == current.size() - 1) path[j] = path[j - 1] + current.get(j); else if(j == 0) path[j] = path[j] + current.get(j); else path[j] = Math.min(path[j - 1], path[j]) + current.get(j); } } int min = path[0]; for(int i = 1; i < path.length; i++){ if(path[i] < min) min = path[i]; } return min; } /** * Given a m x n grid filled with non-negative numbers, * find a path from top left to bottom right which minimizes the sum of all numbers along its path. */ public int minPathSumInGrid(int[][] grid) { int n = grid.length; int m = grid[0].length; int[][] path = new int[n][m]; path[0][0] = grid[0][0]; for(int i = 1; i < n; i++) path[i][0] = path[i-1][0] + grid[i][0]; for(int j = 1; j < m; j++) path[0][j] = path[0][j-1] + grid[0][j]; for(int i = 1; i < n; i++){ for(int j = 1; j < m; j++){ path[i][j] = Math.min(path[i-1][j], path[i][j-1]) + grid[i][j]; } } return path[n-1][m-1]; } /** * Given a 2D binary matrix filled with 0's and 1's, * find the largest square containing all ones and return its area. */ public int maximalSquare(char[][] matrix){ if(matrix.length == 0) return 0; int max = 0; int n = matrix.length; int m = matrix[0].length; int[][] maker = new int[n][m]; for(int i = 0; i < n; i++){ maker[i][0] = matrix[i][0] == '1'? 1 : 0; } for(int j = 1; j < n; j++){ maker[0][j] = matrix[0][j] == '1'? 1 : 0; } for(int i = 1; i < n; i++){ for(int j = 1; j < m; j++){ if(matrix[i][j] == '0') maker[i][j] = 0; else { int smaller = Math.min(maker[i - 1][j], maker[i][j - 1]); maker[i][j] = Math.min(maker[i - 1][j - 1], smaller) + 1; max = Math.max(max, maker[i][j]); } } } return max * max; } /** * Given a 2D binary matrix filled with 0's and 1's, * find the largest rectangle containing all ones and return its area. */ //Time: O(N^2), Space: O(N^2) public static int maximalRectangle(char[][] matrix){ if(matrix.length == 0) return 0; int n = matrix.length; int m = matrix[0].length; int[][] hisgram = new int[n][m]; //for row 0 for(int j = 0; j < m; j++){ hisgram[0][j] = matrix[0][j] == '0'? 0 : 1; } //for row 1 ~ n-1 for(int i = 1; i < n; i++){ for(int j = 0; j < m; j++){ hisgram[i][j] = matrix[i][j] == '0'? 0 : hisgram[i - 1][j] + 1; } } int max = 0; for(int i = 0; i < n; i++){ max = Math.max(max, largestRectangleArea(hisgram[i])); } return max; } //Time: O(N), Space O(N) public static int largestRectangleArea(int[] height) { if(height.length == 0) return 0; Stack<Integer> stack = new Stack<>(); int max = 0; for(int i = 0; i <= height.length; i++){ while(!stack.isEmpty() && (i == height.length || height[i] < height[stack.peek()])){ Integer offset = stack.pop(); int width = stack.isEmpty()? i : i - stack.peek() - 1; max = Math.max(max, width * height[offset]); } stack.push(i); } return max; } //Time: O(N^4), Space O(N^2) public int maximalRectangleO4(char[][] matrix) { if(matrix.length == 0) return 0; int n = matrix.length; int m = matrix[0].length; boolean[][] maker = new boolean[n][m]; int max = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(matrix[i][j] == '0') continue; for(int l = i; l < n; l++){ for(int k = j; k < m; k++){ if(matrix[l][k] == '1' && ((l == i) || maker[l-1][k]) && ((k == j) || maker[l][k-1])){ maker[l][k] = true; max = Math.max((l - i + 1) * (k - j + 1), max); } else { break; } } } } } return max; } }