坐标&接龙型动态规划 - 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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

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 }
View Code

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 }
View Code

二分法: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 }
View Code

 

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 }
View Code

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 }
View Code

以上是关于坐标&接龙型动态规划 - 20181026的主要内容,如果未能解决你的问题,请参考以下文章

「清晰&图解」巧妙的动态规划

动态规划2

动态规划练习

算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )

算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )

ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)