每日算法:动态规划(解码方法、不同二叉搜索树、三角形最短路径之和、买股票的最佳时机)第二天打卡

题目一:解码方法

一条包含字母 A-Z 的消息通过以下方式进行了编码:

'A' -> 1
'B' -> 2
...
'Z' -> 26

给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1:

输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2:

输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
class Solution {
    public int numDecodings(String s) {
        char[] chars = s.toCharArray();
        //前i个字符的编码个数

        int[] dp = new int[chars.length + 1];
        dp[0] = 1;
        dp[1] = chars[0] == '0' ? 0 : 1;
        if(chars.length <= 1)
            return dp[1];
        for(int i = 2;i <= chars.length;i++){
            int n = (chars[i - 2] - '0') * 10 + (chars[i - 1] - '0');
            if(chars[i - 1] == '0' && chars[i - 2] == '0'){
                //两个都是0,直接退出
                return 0;
            }else if(chars[i - 2] == '0'){
                //原字符串尾是0
                dp[i] = dp[i - 1];
            }else if(chars[i - 1] == '0'){
                //新加入的字符是0
                if(n > 26)
                    return 0;
                dp[i] = dp[i - 2];
            }else if(n > 26){
                dp[i] = dp[i - 1];
            }else{
                dp[i] = dp[i - 1] + dp[i - 2];
            }
        }
        return dp[dp.length - 1];
    }
}

分析:dp[i]代表的是前i个字符的编码方法数。dp[1] = 1,表示只有一个字符时候的编码个数,当然就是1啦。dp[0]=1,表示的意义在于:两个字符时,可以是x y,也可以是xy.dp[2]=dp[1]+dp[0]。接下来对于新加入的字符需要判断以下几种情况。例如:121x y。这个时候x表示前一个字符串尾部的字符,y表示新加入的字符。x = chars[i - 2],y = chars[i - 1]。

(1)如果x = ‘0’ 并且 y = '0'。这样无论如何也满足不了条件的。所以直接返回0。

(2)如果x = '0' 而 y != '0'。那么只能是 1210 y这样的分组。因为0y不符合条件。dp[i] = dp[i - 1]。跟没加入字符的编码个数一样。

(3)如果x != '0'而y = '0'。那么只有121 x0 这样分组。因为单独的0不符合条件,dp[i] = dp[i - 2]。大那是x0如果大于26就直接返回了。编码失败。

(4)如果x != '0'而y != '0',并且n>26。那就必须将xy分开。所以还是跟前一个编码个数相同。dp[i] = dp[i - 1]。

(5)如果都不满足的话,就是可以121x y和121 xy这样的组合。所以dp[i] = dp[i - 1] + dp[i - 2]。

最后返回最后一个值,就是编码个数了。

题目二:不同二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

示例:

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3
class Solution {
   public  int numTrees(int n) {
       int[] arr = new int[n + 1];
        arr[0] = 1;
        arr[1] = 1;
        for(int i = 2;i < arr.length;i++){
            for(int j = 1;j <= i;j++){
                arr[i] += arr[j - 1] * arr[i - j];
            }
        }
        return arr[n];
    }
}

arr[i]表示i序列可以构建不同二叉搜索树的个数。例如:当i = 6的时候,那么就需要将以j = 1,2 ... 6为根节点的不同二叉搜索树的个数相加。这就是里面一层for循环的含义,arr[i] += arr[j - 1] * arr[i - j];的意思是:序列[1, 2, 3, 4, 5, 6, 7],现在j=3。那么就需要算以3为根节点的不同二叉搜索树的个数,左子树[1,2],右子树[4,5,6,7]。由于左右子树与实际的个数并无太大的关系,所以左子树实际就是arr[2],右子树实际就是arr[4](个数与具体数值无关)。然后左右子树相乘,因为这是所有组合的情况。

题目三:三角形最短路径之和

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

说明:

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

class Solution {
   public  int minimumTotal(List<List<Integer>> triangle) {
       int[][] temp = new int[triangle.size()][triangle.get(triangle.size()-1).size()];
        //初始化
        temp[0][0] = triangle.get(0).get(0);
        for(int i = 1;i < triangle.size();i++){
            temp[i][0] = triangle.get(i).get(0) + temp[i - 1][0];
            temp[i][i] = triangle.get(i).get(i) + temp[i - 1][i - 1];
        }
        //开搞
        for(int i = 2;i < temp.length;i++){
            for(int j = 1;j < triangle.get(i).size()-1;j++){
                temp[i][j] = Math.min(temp[i - 1][j - 1],temp[i - 1][j]) + triangle.get(i).get(j);
            }
        }
        int min = Integer.MAX_VALUE;
        for(int i = 0;i < temp[0].length;i++){
            if(min > temp[temp.length - 1][i]){
                min = temp[temp.length - 1][i];
            }
        }
        return min;
    }

 
}

这个比较简单。大家看看就可以了。

题目四:买股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length == 0){
            return 0;
        }
        int min = prices[0];
        prices[0] = 0;
        for(int i = 1;i < prices.length;i++){
            if(min > prices[i]){
                min = prices[i];
            }
            prices[i] = prices[i - 1] > prices[i] - min ? prices[i - 1]:prices[i] - min ;
        }
        return prices[prices.length - 1];
    }
}

简单题目。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值