Leetcode516.+Leetcode96. DP问题之求解最长回文子串+BST数目

Leetcode516. Longest Palindromic Subsequence

题目

Given a string s, find the longest palindromic subsequence’s length in s. You may assume that the maximum length of s is 1000.

Example 1:
Input: “bbbab”
Output: 4
One possible longest palindromic subsequence is “bbbb”.

Example 2:
Input: “cbbd”
Output: 2
One possible longest palindromic subsequence is “bb”.

解题分析

这道题是很经典的动态规划问题,我们可以这样考虑:
构建一个n*n的二维数组dp,其中n为字符串长度,dp[i][j]表示下标从i开始到j结束的子串的最长回文串。
很明显,这个数组是关于左上-右下对角线对称的,这里我们考虑对角线的上半部分。
先考虑特殊情况,很明显对角线上i等于j,此时dp[i][j]=1。
再来考虑状态转移方程:
当i不等于j时,有两种情况:一种是s[i]=s[j],一种是s[i]!=s[j]。下面我们分别对这两种情况进行讨论。
当s[i]=s[j]时,表示下标为i和j的字符相同,因此最长回文串应该在原来的基础上向左向右各扩展一个字符,即有dp[i][j]=dp[i+1][j-1]+2。
当s[i]!=s[j]时,表示下标为i和j的字符不相同,因此最长回文串的长度是下标从(i+1)开始到j结束的最长回文串和下标从i开始到(j-1)结束的最长回文串的最大值,即有dp[i][j]=max(dp[i+1][j],dp[i][j-1])。
最后返回dp[0][n-1]即为最终的结果。

源代码

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int size = s.size();
        vector<vector<int>> dp(size, vector<int>(size, 0));
        for (int i = size - 1; i >= 0; i--) {
            dp[i][i] = 1;
            for (int j = i + 1; j < size; j++) {
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                }
                else {
                    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[0][size - 1];
    }
};

Leetcode96. Unique Binary Search Trees

题目

Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?

For example,
Given n = 3, there are a total of 5 unique BST’s.
这里写图片描述

解题分析

给定一个1到n的数列构建BST,我们可以通过枚举序列中每个数字i,将数字i当作BST的根,这样的话数字1到(i-1)就分布在根的左边,数字(i+1)到n就分布在根的右边。这样递归地从子序列中进行构造,可以保证BST是唯一的。

这里我们先来定义两个函数:
G(n):序列长度为n的BST数目
F(i,n):序列从1到n,且数字i作为根的BST数目
很明显,有G(n)=F(1,n)+F(2,n)+…+F(n,n)成立。
特别地,有G(0)=G(1)=1。
现在我们来考虑F(i,n),根据定义,可以知道根的左边有(i-1)个数,根的右边有(n-i)个数。因此有F(i,n)=G(i-1)*G(n-i)成立。
所以G(n)=G(0)*G(n-1)+G(1)*G(n-2)+…+G(n-1)*G(0)。
因此问题也就显而易见了。

源代码

class Solution {
public:
    int numTrees(int n) {
        vector<int> G(n + 1, 0);
        G[0] = G[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                G[i] += G[j - 1] * G[i - j];
            }
        }
        return G[n];
    }
};

以上是我对这两道DP问题的实现的一些想法,有问题还请在评论区讨论留言~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值