动态规划——面试必刷TOP101

动态规划

BM62 斐波那契数列

public class Solution {
    public int Fibonacci(int n) {
        int a=0,b=1,c=0;
        for(int i=0;i<n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return a;
    }
}

BM63 跳台阶

public class Solution {
    public int jumpFloor(int n) {
        int a=1,b=1,c=0;
        for(int i=0;i<n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return a;
    }
}

BM64 最小花费爬楼梯

import java.util.*;

public class Solution {

    public int minCostClimbingStairs (int[] cost) {
        int n=cost.length;
        int[] dp=new int[n];//dp[i]代表爬到这层,再向上爬需要耗费的最小值
        dp[0]=cost[0];
        dp[1]=cost[1];
        for(int i=2;i<n;i++){
            dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i];
        }
        return Math.min(dp[n-1],dp[n-2]);
    }
}

BM65 输出两个字符串的最长公共子序列(不连续)

import java.util.*;

public class Solution {

    public String LCS (String s1, String s2) {
        int m=s1.length(),n=s2.length();
        int[][] dp=new int[m+1][n+1];
         //dp[i][j] 的含义是 s1[0:i-1] 和 s2[0:j-1] 的最长公共子序列的长度。
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                if(s1.charAt(i-1)==s2.charAt(j-1)) dp[i][j]=dp[i-1][j-1]+1;
                else dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
            }
        }
        // return dp[m][n];
        if(dp[m][n]==0) return "-1";
        StringBuilder sb=new StringBuilder();
        while(m>0 && n>0){
            if(s1.charAt(m-1)==s2.charAt(n-1)){
                sb.append(s1.charAt(m-1));
                m--;
                n--;
            }else{
                if(dp[m-1][n]>dp[m][n-1]) m--;
                else n--;
            }
        }
        return sb.reverse().toString();
    }
}

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int n1 = text1.length(),n2 = text2.length();
        int[][] dp = new int[n1 + 1][n2 + 1];
        for (int i = 1; i <= n1; i++) {
            for (int j = 1; j <= n2; j++) {
                if (text1.charAt(i - 1) == text2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[n1][n2];
    }
}

BM66 输出两个字符串的最长公共子串(连续)

import java.util.*;

public class Solution {

    public String LCS (String s1, String s2) {
        int m=s1.length(),n=s2.length();
        int[][] dp=new int[m+1][n+1];
        int res=0,end=0;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                if(s1.charAt(i-1)==s2.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                    if(dp[i][j]>res){
                        res=dp[i][j];
                        end=i-1;
                    }
                }
            }
        }
        String s=s1.substring(end+1-res,end+1);
        return s;
    }
}

class Solution {
    public int findLength(int[] A, int[] B) {
        int m = A.length,n = B.length;
        int[][] dp = new int[m + 1][n + 1];//dp[i][j]代表以A[i-1]与B[j-1]结尾的公共字串的长度
        int res = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A[i - 1] == B[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    res = Math.max(res,dp[i][j]);
                }
            }
        }
        return res;
    }
}

BM67 在m×n的矩阵上从左上角到右下角不同路径的数目

import java.util.*;

public class Solution {

    public int uniquePaths (int m, int n) {
        int[][] dp=new int[m][n];
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i==0) dp[0][j]=1;
                else if(j==0) dp[i][0]=1;
                else dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
}

BM68 在m×n的矩阵上从左上角到右下角的最小路径和

import java.util.*;

public class Solution {

    public int minPathSum (int[][] matrix) {
        int m=matrix.length,n=matrix[0].length;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i==0 && j==0) continue;
                else if(i==0) matrix[0][j]+=matrix[0][j-1];
                else if(j==0) matrix[i][0]+=matrix[i-1][0];
                else matrix[i][j]+=Math.min(matrix[i-1][j],matrix[i][j-1]);
            }
        }
        return matrix[m-1][n-1];
    }
}

BM69 把数字翻译成字符串(‘a’->1, ‘b->2’, … , ‘z->26’)

import java.util.*;

public class Solution {

    public int solve (String nums) {
        if(nums==null ||nums.length()==0) return 0;
        int[] dp = new int[nums.length()+1];
        dp[0]=1;//dp[i]表示nums[0,i-1]的译码方法有多少种。
        dp[1]=nums.charAt(0)=='0'?0:1;
        for(int i=2;i<dp.length;i++){
            //nums[i-1]无法独立编码也无法nums[i-2]和nums[i-1]组合编码
            if(nums.charAt(i-1)=='0' && (nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2')) return 0;
            //只能nums[i-2]和nums[i-1]组合编码
            else if(nums.charAt(i-1)=='0') dp[i] = dp[i-2];
            //nums[i-1]只能独立编码
            else if(nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2' || nums.charAt(i-2)=='2'&& nums.charAt(i-1)>'6' )
                dp[i] = dp[i-1];
            //两种编码方式都可以
            else dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[nums.length()];
    }
}

BM70 兑换零钱

import java.util.*;

public class Solution {
    public int minMoney (int[] arr, int aim) {
        int[] dp=new int[aim+1];
        Arrays.fill(dp,aim+1);
        dp[0]=0;
        for(int i=1;i<=aim;i++){
            for(int j=0;j<arr.length;j++){
                if(i>=arr[j]) dp[i]=Math.min(dp[i],dp[i-arr[j]]+1);
            }
        }
        return dp[aim]>aim?-1:dp[aim];
    }
}

BM71 最长上升子序列(不连续)

import java.util.*;

public class Solution {

    public int LIS(int[] nums) {
        int n=nums.length;
        if(n<=1) return n;
        int[] dp=new int[n];//dp[i]表示以nums[i]结尾的最长上升子序列的长度。
        Arrays.fill(dp,1);
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                if(nums[i]>nums[j]) dp[i]=Math.max(dp[i],dp[j]+1);
            }
        }
        int res=0;
        for(int i=0;i<n;i++) res=Math.max(res,dp[i]);
        return res;
    }
}

BM72 连续子数组的最大和

public class Solution {
    public int FindGreatestSumOfSubArray(int[] arr) {
        for(int i=1;i<arr.length;i++){
            arr[i]+=Math.max(arr[i-1],0);//以arr[i]结尾的连续子数组的最大和
        }
        int res=arr[0];
        for(int i=1;i<arr.length;i++){
            res=Math.max(res,arr[i]);
        }
        return res;
    }
}

BM73 最长回文子串

import java.util.*;

public class Solution {

    public int getLongestPalindrome(String s) {
        int n = s.length();
        //String res = "";
        int res = 0;
        for (int i = 0; i < 2 * n - 1; i++) {
            int l = i / 2;
            int r = l + i % 2;
            while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
                res=Math.max(res,r-l+1);
                //String tmp = s.substring(l, r + 1);
                //if (tmp.length() > res.length()) res = tmp;
                l--;
                r++;
            }
        }
        return res;
    }
}
647. 回文子串的数目
class Solution6472 {
    public int countSubstrings(String s) {
        int n = s.length();
        int res = 0;
        for (int i = 0; i < 2 * n - 1; i++) {
            int l = i / 2;
            int r = l + i % 2;
            while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
                res++;
                l--;
                r++;
            }
        }
        return res;
    }
}

BM75 编辑距离

import java.util.*;

public class Solution {
/*
dp[i][j] 代表 word1[0,i-1]位置转换成 word2[0,j-1]位置需要最少步数
当 word1[i] == word2[j],dp[i][j] = dp[i-1][j-1];
当 word1[i] != word2[j],dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
其中,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作。
*/
    public int editDistance(String word1, String word2) {
        int n1=word1.length(),n2=word2.length();
        int[][]dp=new int [n1+1][n2+1];
        for(int j=1;j<=n2;j++) dp[0][j]=dp[0][j-1]+1;//插入
        for(int i=1;i<=n1;i++) dp[i][0]=dp[i-1][0]+1;//删除
        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                if(word1.charAt(i-1)==word2.charAt(j-1)) dp[i][j]=dp[i-1][j-1];
                else dp[i][j]=Math.min(Math.min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
            }
        }
        return dp[n1][n2];
    }
}

BM76 正则表达式匹配

import java.util.*;
/*
最后来个归纳:
如果 p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1];
如果 p.charAt(j) == '.' : dp[i][j] = dp[i-1][j-1];
如果 p.charAt(j) == '*':
    如果 p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2] //in this case, a* only counts as empty
    如果 p.charAt(j-1) == s.charAt(i) or p.charAt(j-1) == '.':
        dp[i][j] = dp[i-1][j] //in this case, a* counts as multiple a
        or dp[i][j] = dp[i][j-1] // in this case, a* counts as single a
        or dp[i][j] = dp[i][j-2] // in this case, a* counts as empty
*/
public class Solution {
    public boolean match(String s, String p) {
        //往原字符头部插入空格,这样得到 char 数组是从 1 开始,
        //而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
        s = " " + s;
        p = " " + p;  
        int n = s.length(),m = p.length();
        boolean[][] dp = new boolean[n][m];//dp[i][j]表示s[0,i]与p[0,j]是否匹配
        dp[0][0] = true;
        if(p.charAt(1) == s.charAt(1) || p.charAt(1) == '.')dp[1][1] = true;
        for(int i = 0;i < n;i++){
            for(int j = 1;j < m;j++){
                if(p.charAt(j) != '*'){
                    if(i > 0)dp[i][j] = dp[i-1][j-1] && 
                        (p.charAt(j) == s.charAt(i) || p.charAt(j) == '.');
                }else {
                   if(i > 0) dp[i][j] = dp[i][j-2] || dp[i-1][j] && 
                       (p.charAt(j-1) == s.charAt(i) || p.charAt(j-1) == '.');
                   else{
                       dp[i][j] = dp[i][j - 2]; 
                   }
                }
            }
        }
        return dp[n-1][m-1];
    }
}

BM77 最长的括号子串

import java.util.*;

public class Solution {
    Stack<Integer> stack = new Stack<>();
    public int longestValidParentheses(String s) {
        if(s==null || s.length()==0) return 0;
        char[] c = s.toCharArray();
        int[] mark = new int[s.length()]; 
        for(int i=0; i<s.length(); i++){
            if(c[i]=='(') stack.push(i);//对于遇到的每个'(',我们将它的下标放入栈中
            else{
                if(!stack.isEmpty() && c[stack.peek()]=='('){
                    mark[stack.pop()] = 1;//与当前右括号所匹配的左括号
                    mark[i] = 1;//当前右括号   
                }
            }
        }
        int max = 0,cur = 0;
        for(int i:mark){
            if(i==1){
                cur ++;
                max = Math.max(max,cur);
            }else cur = 0;
        }
        return max;
    }
}

BM78 打家劫舍(一)

import java.util.*;

public class Solution {

    public int rob (int[] nums) {
        int n=nums.length;
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=nums[0];
        for(int i=2;i<=n;i++){
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
        }
        return dp[n];
    }
}

BM79 打家劫舍(二)

import java.util.*;

public class Solution {

    public int rob (int[] nums) {
        int n=nums.length;
        //一个是从0到n-1,另一个是从1到n,然后返回两个结果最大的。
        int rob1=getRob(Arrays.copyOfRange(nums,0,n-1));
        int rob2=getRob(Arrays.copyOfRange(nums,1,n));
        return Math.max(rob1,rob2);       
    }
    
    private int getRob(int[] nums){  
        int n=nums.length;
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=nums[0];
        for(int i=2;i<=n;i++){
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
        }
        return dp[n];
    }
}

BM80 买卖股票的最好时机(一)

import java.util.*;

public class Solution {

    public int maxProfit (int[] prices) {
        int cost=Integer.MAX_VALUE,res=0;
        for(int price:prices){
            cost=Math.min(price,cost);
            res=Math.max(res,price-cost);
        }
        return res;
    }
}

BM81 买卖股票的最好时机(二)

import java.util.*;

public class Solution {

    public int maxProfit (int[] prices) {
        int res=0;
        for(int i=1;i<prices.length;i++){
            if(prices[i]>prices[i-1]) res+=prices[i]-prices[i-1];
        }
        return res;
    }
}

BM82 买卖股票的最好时机(三)

import java.util.*;

public class Solution {

    public int maxProfit(int[] prices) {
        int firstBuy = Integer.MIN_VALUE, firstSell = 0;
        int secondBuy = Integer.MIN_VALUE, secondSell = 0;
        for(int p : prices) {
            firstBuy = Math.max(firstBuy, -p);
            firstSell = Math.max(firstSell, firstBuy + p);
            secondBuy = Math.max(secondBuy, firstSell - p);
            secondSell = Math.max(secondSell, secondBuy + p);
        }
        return secondSell;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值