您的位置:首页 > 其它

Leetcode动态规划题答案

2016-09-09 14:29 369 查看
动态规划一直是比较难的题目,在刷leetcode时候,遇到的动态规划不下于10道题,现在挑出来一些给大家分享下,希望大家在接下来的秋招有个好的收成!

DP就是时间换空间,将一个递归过程转换成表,往往是二维的表,主要是如何变才是重点。

leetcode的第32题:最长有效括号,将真不看答案我死的没想到可以用动态规划的,我是递归实现,可惜超时了。。

import java.util.Stack;

public class 动态规划最长有效的括号_32 {
public static void main(String[] args) {
动态规划最长有效的括号_32 test = new 动态规划最长有效的括号_32();
int longestValidParentheses = test
.longestValidParentheses(")((()))()(())))");
System.out.println(longestValidParentheses);
}

public int longestValidParentheses(String s) {
Stack<Integer> stack = new Stack<Integer>();
int[] S = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push(i);
} else {
if (!stack.isEmpty()) {
S[i] = 1;
S[stack.pop()] = 1;
}
}
}
int maxLength = 0;
int curLength = 0;
// 找到最长怜恤1子串
for (int i = 0; i < S.length; i++) {
if (S[i] == 1) {
curLength++;
} else {
curLength = 0;
}
if (curLength > maxLength) {
maxLength = curLength;
}
}
return maxLength;
}

public int longestValidParentheses2(String s) {
//以i开始到字符串结束的最长有效括号长度
int[] dp = new int[s.length()];
int maxLen = 0;
for(int i = s.length()-2; i >=0; i--){
//s[i]是字符串下标为i的括号
if(s.charAt(i)=='('){
//如果s[i-1]是左括号,如果i + d[i] + 1是右括号的话,那d[i-1] = d[i] + 2
int end = i + dp[i+1] + 1;
if(end < s.length() && s.charAt(end)==')'){
dp[i] = dp[i+1] + 2;
//如果不是则为0。如果s[i-1]是右括号,因为不可能有右括号开头的括号对,所以d[i-1] = 0。
if(end + 1 < s.length()){
dp[i] += dp[end + 1];
}
}
}
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
}
}


leetcode的第53题:最大连续子序列
这道题看各种书上都有介绍,没什么好说的,如果不会说明你压根一本面试书都没看

public class 动态规划之最大连续和的子序列_53 {
public int maxSubArray(int[] nums) {
int nEnd=nums[0];
int nAll=nums[0];
for (int i = 1; i < nums.length; i++) {
nEnd=Math.max(nEnd+nums[i], nums[i]);
nAll=Math.max(nAll, nEnd);
}
return nAll;
}
}


leetcode的第62-63-64题,棋盘上的路径问题:这个比较好理解,就是左边,上边的当前位置的影响而已:
public class 动态规划之棋盘上所有不同路径_62 {
public int uniquePaths(int m, int n) {
int [][]dp=new int [m]
;
for (int i = 0; i < m; i++) {
dp[i][0]=1;
}
for (int i = 0; i < n; i++) {
dp[0][i]=1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j <n; j++) {
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}

public class 动态规划之迷宫中能走的所有不同路径_63 {
public static void main(String[] args) {
动态规划之迷宫中能走的所有不同路径_63 test = new 动态规划之迷宫中能走的所有不同路径_63();
int[][] obstacleGrid = new int[][] { { 0, 1 } };
int uniquePathsWithObstacles = test
.uniquePathsWithObstacles(obstacleGrid);
System.out.println(uniquePathsWithObstacles);
}

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
if (obstacleGrid == null) {
return 0;
}
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m]
;
if (obstacleGrid[0][0] == 1) {
return 0;
}
dp[0][0] = 1;
for (int i = 1; i < m; i++) {
if (obstacleGrid[i][0] == 0) {
dp[i][0] = dp[i - 1][0];
}
}
for (int i = 1; i < n; i++) {
if (obstacleGrid[0][i] == 0) {
dp[0][i] = dp[0][i - 1];
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (obstacleGrid[i][j] == 0) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m - 1][n - 1];
}
}

public class 动态规划之棋盘上路径所有元素和最小值_64 {
public int minPathSum(int[][] grid) {
if (grid == null) {
return 0;
}
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m]
;
dp[0][0] = grid[0][0];
for (int i = 1; i < m; i++) {
dp[i][0] = grid[i][0] + dp[i - 1][0];
}
for (int i = 1; i < n; i++) {
dp[0][i] = grid[0][i] + dp[0][i - 1];
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
}
leetcode的72题:字符串的替换,删除,插入距离代价,其实这一题可以改编成替换代价,删除代价和插入代价不等。
public class 动态规划之计算字符串的距离_72 {
public int minDistance(String word1, String word2) {
int n=word1.length();
int m=word2.length();
//A中前i个元素转到B中前j个元素所需要的最小代价
int [][]dp=new int [n+1][m+1];
//表示A前i个元素转为B前0个元素的操作是需要i次的
for (int i = 0; i <=n; i++) {
dp[i][0]=i;
}
//表示A中前0个元素转为B的前i个元素的操作次数是i次
for (int i = 0; i <=m; i++) {
dp[0][i]=i;
}
for (int i = 1; i <=n; i++) {
for (int j = 1; j <=m; j++) {
if (word1.charAt(i-1)==word2.charAt(j-1)) {
dp[i][j]=dp[i-1][j-1];
}else{
//dp[i-1][j-1]+1代表是替换一个元素,
//dp[i][j-1]+1代表是添加一个元素,
//dp[i-1][j]+1代表是删除一个元素
dp[i][j]=Math.min(Math.min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+1);
}
}
}
return dp
[m];
}
}


leetcode:第91题解码方式,当时我对这道题有点懵逼,为什么只判断开头不为0,中间有0怎么办啊,,哎说多都是泪,算法真难学:
public class 动态规划之解码方式_91 {
public static void main(String[] args) {
动态规划之解码方式_91 test=new 动态规划之解码方式_91();
int numDecodings = test.numDecodings("12121");
System.out.println(numDecodings);
}

public int numDecodings(String s) {
if (s.length()==0||s.startsWith("0")) {
return 0;
}
int len=s.length()+1;
int [] dp=new int[len];
dp[0]=1;
dp[1]=1;
for (int i = 2; i < len; i++) {
int t=Integer.parseInt(s.substring(i-2,i));
if (10<=t&&t<=26) {
dp[i]+=dp[i-2];
}
int temp=Integer.parseInt(s.substring(i-1,i));
if (1<=temp&&temp<=9) {
dp[i]+=dp[i-1];
}
}
return dp[len-1];
}
}
leetcode:第96题二叉树的生成方式:
import java.util.ArrayList;
import java.util.List;

public class 动态规划之二叉树生成总数_96 {
public static void main(String[] args) {
动态规划之二叉树生成总数_96 test = new 动态规划之二叉树生成总数_96();
// List<TreeNode> generateTrees = test.generateTrees(3);
int nums = test.generateTreesCount(2);
System.out.println(nums);
}

// BST树:以i为根节点的树,其左子树由[0, i-1]构成, 其右子树由[i+1, n]构成。
// 动态规划状态为count
,count
表示到正整数i为止的BST个数 ;
private int generateTreesCount(int n) {
int[] dp = new int[n + 1];
dp[0] = 1;// 表示为空节点,情况只有一种
for (int i = 1; i <= n; i++) {// 表示以i為根节点
for (int j = 0; j < i; j++) {// j表示左字数的构造种类,i-j-1表示右字数构造种类
dp[i] += dp[j] * dp[i - j - 1];// 左字数种类*右字数种类
}
}
return dp
;
}

public List<TreeNode> generateTrees(int n) {
if (n<1) {
return new ArrayList<>();
}
return getnereteTree(1, n);
}

private List<TreeNode> getnereteTree(int left, int right) {
List<TreeNode> list = new ArrayList<>();
if (left > right) {
list.add(null);
return list;
}
for (int i = left; i <= right; i++) {
List<TreeNode> lefts = getnereteTree(left, i - 1);// 以i作为根节点,左子树由[1,i-1]构成
List<TreeNode> rights = getnereteTree(i + 1, right);// 右子树由[i+1, n]构成
for (int j = 0; j < lefts.size(); j++) {
for (int k = 0; k < rights.size(); k++) {
TreeNode root = new TreeNode(i);
root.left = lefts.get(j);
root.right = rights.get(k);
list.add(root);// 存储所有可能行
}
}
}
return list;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息