最长递增子序列,交错字符串

第一题:

代码如下:

cpp 复制代码
int lengthOfLIS(vector<int>& nums)
{
	//dp[i]表示以第i个元素为结尾的最长子序列的长度
	int n = nums.size();
	int res = 1;
	vector<int> dp(n, 1);
	for (int i = 1; i < n; ++i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (nums[i] > nums[j])
				dp[i] = max(dp[i], dp[j] + 1);
		}
		res = max(res, dp[i]);
	}
	return res;
}

思路整理:

使用动态规划,线性dp就可以解决。

具体状态表示:dp[i]表示以第i个位置为结尾的最长子序列的长度。

初始化:因为最长递增子序列的长度至少为1,所以不妨将所有位置的长度都初始化为1。

填写过程以及逻辑:因为第一个位置为结尾的子序列长度为1,所以i从1下标开始,以该位置元素为结尾的序列有两种情况。

<1>该元素跟在其前面的任意一个元素后组成一个递增子序列。

<2>该元素比前面任意一个元素都小,所以只能自己成为单独的一个递增子序列。

因为在初始化时,已经将第二种情况考虑到了,所以每个位置都为1,若是第二种情况,就不必更新了,只考虑第一种情况就行。即

cpp 复制代码
if (nums[i] > nums[j])
				dp[i] = max(dp[i], dp[j] + 1);

表示i位置的元素大于j位置的元素时,dp[i]取dp[i]和dp[j] + 1两者之间的最大值。结合状态表示来理解。每当dp[i]更新完之后,可以更新一下最终结果,走完之后,就可以返回最终结果res了。

时空复杂度:时间复杂度O(n * n),空间复杂度O(n)

第二题:

代码如下:

cpp 复制代码
bool isInterleave(string s1, string s2, string s3) 
{
    //dp[i][j]表示s1的[0,i]部分和s2的[0,j]能否构成s3的[i,j]部分
    int m = s1.size();
    int n = s2.size();
    if (m + n != s3.size())
        return false;
    s1 = " " + s1;
    s2 = " " + s2;
    s3 = " " + s3;
    vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
    for (int i = 1; i <= n; ++i)//s1为空
    {
        if (s2[i] == s3[i]) dp[0][i] = true;
        else
            break;
    }
    for (int i = 1; i <= m; ++i)//s2为空
    {
        if (s1[i] == s3[i]) dp[i][0] = true;
        else
            break;
    }
    dp[0][0] = true;
    for (int i = 1; i <= m; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            dp[i][j] = (s1[i] == s3[i + j] && dp[i - 1][j]
                || s2[j] == s3[i + j] && dp[i][j - 1]);
        }
    }
    return dp[m][n];
}

思路整理:

动态规划,用到二维dp。在此之前,需要进行一个问题的转化,其实就是判断字符串s1能否由s2和s3组成。

具体状态表示:dp[i][j]表示s1的[0,i]部分和s2的[0,j]能否构成s3的[i,j]部分。

初始化:dp数组多开一行一列,便于结合状态定义来解决该问题,为了使得字符串位置一一对应,可以选择在字符串前加上空格符来进行占位,不表示额外含义,只是为了好进行对应。默认开辟的空间内都是false,结合状态定义,初始化第一行,即dp[0][i],当s1为空,就只有s2来组成s3,当s2[i] == s3[i]时,dp[0][i] = true,否则就是false,同理初始化第一列,即dp[i][0],当s2为空,只有s1来组成s3,当s1[i] == s3[i]时,dp[i][0] = true,否则就是false。dp[0][0]为true,确保后面的结果正确。

填写过程以及逻辑:如果s1的长度加上s2的长度和s3的长度不一致,那么就说明一定不能组成s3,返回false,否则dp[i][j]为真的情况有两种:

<1>s1[i] == s3[i + j] && dp[i - 1][j] == true,即s1的i位置和s3的i + j位置相同,并且s1的0~i-1位置和s2的0~j位置能构成s3的当前位置的其余部分。

<2>s2[j] == s3[i + j] && dp[i][j - 1] == true,即s2的i位置和s3的i + j位置相同,并且s1的0~i位置和s2的0~j - 1位置能构成s3的当前位置的其余部分。

最终返回dp[m][n]表示s1和s2能否构成s3。

水平有限,欢迎指正。

相关推荐
CoovallyAIHub24 分钟前
MSD-DETR:面向机车弹簧检测的可变形注意力Detection Transformer
算法·架构
CoovallyAIHub28 分钟前
不改权重、不用训练!BEM用背景记忆抑制固定摄像头误检,YOLO/RT-DETR全系有效
算法·架构·github
Struggle_975533 分钟前
算法知识-从递归入手三维动态规划
算法·动态规划
yuan1999738 分钟前
使用模糊逻辑算法进行路径规划(MATLAB实现)
开发语言·算法·matlab
不才小强42 分钟前
线性表详解:顺序与链式存储
数据结构·算法
CoovallyAIHub42 分钟前
上交+阿里 | Interactive ASR:Agent框架做语音识别交互纠错,1轮交互语义错误率降57%
算法·架构·github
Aaron15881 小时前
8通道测向系统演示科研套件
人工智能·算法·fpga开发·硬件工程·信息与通信·信号处理·基带工程
计算机安禾1 小时前
【数据结构与算法】第42篇:并查集(Disjoint Set Union)
c语言·数据结构·c++·算法·链表·排序算法·深度优先
吃着火锅x唱着歌1 小时前
LeetCode 150.逆波兰表达式求值
linux·算法·leetcode
YuanDaima20481 小时前
二分查找基础原理与题目说明
开发语言·数据结构·人工智能·笔记·python·算法