坐标&接龙型动态规划 - 20181026
Posted lizzyluvcoding
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了坐标&接龙型动态规划 - 20181026相关的知识,希望对你有一定的参考价值。
109. Triangle
此题还可以用DFS,记忆化搜索去做,二刷实现
1 public class Solution { 2 /** 3 * @param triangle: a list of lists of integers 4 * @return: An integer, minimum path sum 5 */ 6 public int minimumTotal(int[][] triangle) { 7 // write your code here 8 if (triangle == null || triangle.length == 0 || triangle[0] == null || triangle[0].length == 0) { 9 return -1; 10 } 11 12 int r = triangle.length; 13 14 //定义f[][]为0,0到x,y的最小路径 15 int[][] f = new int[r][r]; 16 f[0][0] = triangle[0][0]; 17 //初始化两条边 18 for (int i = 1; i < r; i++) { 19 f[i][0] = f[i - 1][0] + triangle[i][0]; 20 f[i][i] = f[i - 1][i - 1] + triangle[i][i]; 21 } 22 23 for (int i = 1; i < r; i++) 24 for (int j = 1; j < i; j++) { 25 f[i][j] = triangle[i][j] + Math.min(f[i - 1][j], f[i - 1][j - 1]); 26 } 27 28 int minTotal = f[r-1][0]; 29 for (int i = 0; i < r; i++) { 30 minTotal = f[r - 1][i] < minTotal ? f[r - 1][i] : minTotal; 31 } 32 return minTotal; 33 } 34 }
110. Minimum Path Sum
1 public class Solution { 2 /** 3 * @param grid: a list of lists of integers 4 * @return: An integer, minimizes the sum of all numbers along its path 5 */ 6 public int minPathSum(int[][] grid) { 7 // write your code here 8 if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) { 9 return -1; 10 } 11 12 //定义f为0,0到x,y的最小路径和 13 int r = grid.length; 14 int c = grid[0].length; 15 int[][] f = new int[r][c]; 16 17 f[0][0] = grid[0][0]; 18 //初始化两条边 19 for (int i = 1; i < c; i++) { 20 f[0][i] = grid[0][i] + f[0][i - 1]; 21 } 22 for (int i = 1; i < r; i++) { 23 f[i][0] = grid[i][0] + f[i - 1][0]; 24 } 25 26 for (int i = 1; i < r; i++) 27 for (int j = 1; j < c; j++) { 28 f[i][j] = grid[i][j] + Math.min(f[i - 1][j], f[i][j - 1]); 29 } 30 return f[r - 1][c - 1]; 31 } 32 }
114. Unique Paths
1 public class Solution { 2 /** 3 * @param m: positive integer (1 <= m <= 100) 4 * @param n: positive integer (1 <= n <= 100) 5 * @return: An integer 6 */ 7 public int uniquePaths(int m, int n) { 8 // write your code here 9 if (m <= 0 || n <= 0) { 10 return -1; 11 } 12 13 int[][] sum = new int[m][n]; 14 15 for (int i = 0; i < m; i++) { 16 sum[i][0] = 1; 17 } 18 for (int i = 0; i < n; i++) { 19 sum[0][i] = 1; 20 } 21 22 for (int i = 1; i < m; i++) 23 for (int j = 1; j < n; j++) { 24 sum[i][j] = sum[i - 1][j] + sum[i][j - 1]; 25 } 26 27 return sum[m - 1][n - 1]; 28 } 29 }
111. Climbing Stairs
1 public class Solution { 2 /** 3 * @param n: An integer 4 * @return: An integer 5 */ 6 public int climbStairs(int n) { 7 // write your code here 8 if (n <= 0) { 9 return 0; 10 } 11 if(n==1){ 12 return 1; 13 } 14 int[] f = new int[n+1]; 15 f[1] = 1; 16 f[2] = 2; 17 18 for (int i = 3; i <= n; i++) { 19 f[i] = f[i - 1] + f[i - 2]; 20 } 21 return f[n]; 22 } 23 }
Method1: DP
116. Jump Game
1 public class Solution { 2 /** 3 * @param A: A list of integers 4 * @return: A boolean 5 */ 6 public boolean canJump(int[] A) { 7 // write your code here 8 if (A == null || A.length == 0) { 9 return false; 10 } 11 12 boolean[] can = new boolean[A.length]; 13 can[0] = true; 14 for (int i = 0; i < A.length; i++) { 15 int canJumpLen = A[i]; 16 for (int j = 0; j <= canJumpLen; j++) { 17 if (i + j > A.length - 1) { 18 break; 19 } 20 can[i + j] = true & can[i]; 21 } 22 } 23 return can[A.length - 1]; 24 25 } 26 27 }
117. Jump Game II
1 public class Solution { 2 /** 3 * @param A: A list of integers 4 * @return: An integer 5 */ 6 public int jump(int[] A) { 7 // write your code here 8 if(A==null || A.length==0){ 9 return 0; 10 } 11 12 int[] f = new int[A.length]; 13 f[0] = 0; 14 for(int i=1;i<A.length;i++){ 15 f[i] = Integer.MAX_VALUE; 16 for(int j=0;j<i;j++){ 17 if(j+A[j]>=i){ 18 f[i] = Math.min(f[i],f[j]+1); 19 } 20 } 21 } 22 return f[A.length-1]; 23 } 24 }
Method2:Greedy(二刷)
76. Longest Increasing Subsequence
1 public class Solution { 2 /** 3 * @param nums: An integer array 4 * @return: The length of LIS (longest increasing subsequence) 5 */ 6 public int longestIncreasingSubsequence(int[] nums) { 7 // write your code here 8 if (nums == null || nums.length == 0) { 9 return 0; 10 } 11 12 int[] f = new int[nums.length]; 13 f[0] = 1; 14 for (int i = 0; i < nums.length; i++) { 15 f[i] = 1; 16 for (int j = 0; j < i; j++) { 17 if (nums[j] < nums[i]) { 18 f[i] = Math.max(f[i], f[j] + 1); 19 } 20 } 21 } 22 int maxLen = 1; 23 for (int i = 0; i < f.length; i++) { 24 maxLen = Math.max(f[i], maxLen); 25 } 26 return maxLen; 27 } 28 }
二分法:AC的答案是错误的,二分时重复情况应踢掉,见602题解答
1 public class Solution { 2 /** 3 * @param nums: An integer array 4 * @return: The length of LIS (longest increasing subsequence) 5 */ 6 public int longestIncreasingSubsequence(int[] nums) { 7 // write your code here 8 if (nums == null || nums.length == 0) { 9 return 0; 10 } 11 12 int[] tails = new int[nums.length]; 13 tails[0] = nums[0]; 14 int len = 1; 15 for (int i = 1; i < nums.length; i++) { 16 if (nums[i] == tails[0] || nums[i] == tails[len - 1]) { 17 continue; 18 } 19 if (nums[i] < tails[0]) { 20 tails[0] = nums[i]; 21 continue; 22 } 23 if (nums[i] > tails[len - 1]) { 24 tails[len] = nums[i]; 25 len++; 26 continue; 27 } 28 29 if (nums[i] > tails[0] && nums[i] < tails[len - 1]) { 30 //第一个大于nums[i]的位置 31 int index = binarySearch(tails, nums[i],len); 32 if (index >= 0 && index <= len - 1) { 33 tails[index] = nums[i]; 34 } 35 } 36 } 37 return len; 38 } 39 40 public int binarySearch(int[] nums, int target,int len) { 41 if (nums == null || nums.length == 0) { 42 return -1; 43 } 44 45 int start = 0; 46 int end = len - 1; 47 while (start + 1 < end) { 48 int mid = start + (end - start) / 2; 49 if (nums[mid] == target) { 50 start = mid; 51 } 52 if (nums[mid] > target) { 53 end = mid; 54 } 55 if (nums[mid] < target) { 56 start = mid; 57 } 58 } 59 if (nums[start] > target) { 60 return start; 61 } 62 if (nums[end] > target) { 63 return end; 64 } 65 return -1; 66 } 67 }
602. Russian Doll Envelopes
DP会TLE,考虑用二分优化时间复杂度
method1:DP(时间复杂度o(n^2))
1 public class Solution { 2 /* 3 * @param envelopes: a number of envelopes with widths and heights 4 * @return: the maximum number of envelopes 5 */ 6 public int maxEnvelopes(int[][] envelopes) { 7 // write your code here 8 if (envelopes == null || envelopes.length == 0 || envelopes[0] == null || envelopes[0].length == 0) { 9 return 0; 10 } 11 12 Comparator<int[]> comparator = new Comparator<int[]>() { 13 @Override 14 public int compare(int[] o1, int[] o2) { 15 return o1[0] == o2[0] ? o1[1] - o2[1] : o1[0] - o2[0]; 16 } 17 }; 18 19 Arrays.sort(envelopes, comparator); 20 int[] f = new int[envelopes.length]; 21 f[0] = 1; 22 23 int maxLen = 1; 24 for (int i = 1; i < f.length; i++) { 25 f[i] = 1; 26 for (int j = 0; j < i; j++) { 27 if (envelopes[i][0] > envelopes[j][0] && envelopes[i][1] > envelopes[j][1]) 28 f[i] = Math.max(f[i], f[j] + 1); 29 } 30 maxLen = Math.max(f[i], maxLen); 31 } 32 33 return maxLen; 34 } 35 }
method2: 二分(o(NlogN))注意初次排序时按宽度递增排序,宽度相同时高度递减,将问题简化为求最长子序列(递减可以易于去除宽度相同的序列)
1 public class Solution { 2 /* 3 * @param envelopes: a number of envelopes with widths and heights 4 * @return: the maximum number of envelopes 5 */ 6 public int maxEnvelopes(int[][] envelopes) { 7 // write your code here 8 if (envelopes == null || envelopes.length == 0 || envelopes[0] == null || envelopes[0].length == 0) { 9 return 0; 10 } 11 12 //按宽度递增排序,宽度相同时高度递减 求最长子序列(递减可以易于去除宽度相同的序列) 13 Comparator<int[]> comparator = new Comparator<int[]>() { 14 @Override 15 public int compare(int[] o1, int[] o2) { 16 return o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]; 17 } 18 }; 19 20 Arrays.sort(envelopes, comparator); 21 return longestIncreasingSubsequence(envelopes); 22 } 23 24 25 public int longestIncreasingSubsequence(int[][] envelopes) { 26 // write your code here 27 if (envelopes == null || envelopes.length == 0) { 28 return 0; 29 } 30 31 32 int[] tails = new int[envelopes.length]; 33 tails[0] = envelopes[0][1]; 34 int len = 1; 35 for (int i = 1; i < envelopes.length; i++) { 36 if (envelopes[i][1] == tails[0] || envelopes[i][1] == tails[len - 1]) { 37 continue; 38 } 39 if (envelopes[i][1] < tails[0]) { 40 tails[0] = envelopes[i][1]; 41 continue; 42 } 43 if (envelopes[i][1] > tails[len - 1]) { 44 tails[len] = envelopes[i][1]; 45 len++; 46 continue; 47 } 48 49 if (envelopes[i][1] > tails[0] && envelopes[i][1] < tails[len - 1]) { 50 //第一个大于nums[i]的位置 51 int index = binarySearch(tails, envelopes[i][1],len); 52 if (index >= 0 && index <= len - 1) { 53 tails[index] = envelopes[i][1]; 54 } 55 } 56 } 57 return len; 58 } 59 60 public int binarySearch(int[] nums, int target,int len) { 61 if (nums == null || nums.length == 0) { 62 return -1; 63 } 64 65 int start = 0; 66 int end = len - 1; 67 while (start + 1 < end) { 68 int mid = start + (end - start) / 2; 69 if (nums[mid] == target) { 70 //重复情况要踢掉,以免替换了后面的大数,会造成wrong answer 71 return -1; 72 } 73 if (nums[mid] > target) { 74 end = mid; 75 } 76 if (nums[mid] < target) { 77 start = mid; 78 } 79 } 80 if (nums[start] > target) { 81 return start; 82 } 83 if (nums[end] > target) { 84 return end; 85 } 86 return -1; 87 } 88 89 }
以上是关于坐标&接龙型动态规划 - 20181026的主要内容,如果未能解决你的问题,请参考以下文章
算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )
算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )