【刷题汇总 -- 爱丽丝的人偶、集合、最长回文子序列】

今日刷题汇总 - day021

1、爱丽丝的人偶

1.1、题目

在这里插入图片描述

1.2、思路

读完题,知道让我们将一个有序的身高序列重新排队,要求除了第一个和最后一个元素外,不能让x的前、后元素一个比它高,一个比它矮,求怎么摆能够满足上述条件并摆放所有玩偶。那么,分析题目和示例,得知,不能让x的前后具有相异性,那么要么全部比x大,要么全部比x小即可。既然如此,我第一个摆放最小的1,第二个摆放最大的n,再接着拜访次小的2,再接着摆放次大的n-1即可。发现这个规律后,就按照这个逻辑实现即可。接下来,就是程序实现。

1.3、程序实现

根据题目和思路分析,由于是有序序列,那么直接按照先放置小的,再放大的顺序循环即可。

#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;
    
    int left = 1;
    int right = n;
    while(left <= right)
    {
        cout << left << " ";
        left++;
        if(left <= right)
        {
            cout << right << " ";
            right--;
        }
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述

2、集合

2.1、题目

在这里插入图片描述

2.2、思路

读完题,知道要求实现两个集合的相加,其中相加之后的集合中不能出现相同元素。首先,能够想到得基本思想就是归并排序,先把A,B集合sort排序,然后进行归并排序,最后去重输出。那么既然如此,简化思路就是将A,B集合需要放入同一个容器中,然后排序+去重即可。恰好得是C++提供了一个set关联式容器,set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。需要注意的是set中元素的值不能直接被改变。

底层本质:C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

所以对于这道题,使用set可以完美解决问题。

2.3、程序实现 – set

首先,按照要求和思路分析,引入#include 头文件,然后采用预处理方式按照题目输入和插入到同一个容器s中,自动完成排序与去重,最后直接遍历输出即可。

#include <iostream>
#include <set>
using namespace std;

int main()
{
    int n,m;
    cin >> n >> m;

    set<int> s;
    int A,B;
    for(int i = 0;i < n;i++)
    {
        cin >> A;
        s.insert(A);
    }
    for(int i = 0;i < m;i++)
    {
        cin >> B;
        s.insert(B);
    }

    
    for(auto num : s)
    {
        cout << num << " ";
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述

3、最长回文子序列

3.1、题目

在这里插入图片描述

3.2、思路

读完题,知道跟之前做过的题连续子数组最大和类似,都不是固定长度的,可以是任意长度的可能,所以不采用滑动窗口而采用dp动态规划。求一个字符串中最长的回文子序列,其中,本题中子序列字符串任意位置删除k(len(s)>=k>=0)个字符后留下的子串。那么子序列是不定长的情况,所以动态规划法需要状态表示,以dp[i][j]表示,在第 [ i , j ] 区间的回文字符串最大长度,推导状态转移方程,当回文字符串长度为一个字符时,则 i 等于 j ,直接输出1即可,然后要求最大回文串,那么当字符串本身就是回文时就是最大长度,另外本身不是字符串的情况下,就又分为左边去掉一个字符组成的区间dp[i+1][j],右边去掉一个字符组成的区间dp[i][j-1]为次打区间,如果满足回文时就是最大回文。所以状态转移方程情况分为:
a、当i = j 的时候,只有⼀个字符,⻓度为1;
b、当i < j 的时候,分情况讨论:
(1)、str[i] == str[j]时:dp[i][j] = dp[i + 1][j - 1] + 2;
(2)、str[i] != str[j]时:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
另外注意初始化为了处理长度为1时的情况,所以置dp[i][i] = 1;表示每个单独的字符都是长度为1的回文子序列 和 返回值,长度为n的字符串满足[0,n)区间,所以输出是dp[0][n-1]即可。那么接下来就是,程序实现。

3.3、程序实现 – dp

首先根据思路分析得出即可

  1. 状态表⽰: dp[i][j] 表⽰:字符串[i, j] 范围内的最⻓回⽂⼦序列的⻓度;
  2. 状态转移⽅程:
    a、当i = j 的时候,只有⼀个字符,⻓度为1;
    b、当i < j 的时候,分情况讨论:
    c、s[i] == s[j]:dp[i][j] = dp[i + 1][j - 1] + 2;
    d、s[i] != s[j]:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
  3. 初始化: dp[i][i] = 1 。
  4. 返回值: dp[0][n - 1] 。
#include <iostream>
#include <string>
using namespace std;

int dp[1001][1001];

int main()
{
    string str;
    cin >> str;
    int n = str.size();

    for(int i = n-1;i >= 0;i--)
    {
        dp[i][i] = 1;
        for(int j = i + 1;j < n;j++)
        {
            if(str[i] == str[j])
                dp[i][j] = dp[i+1][j-1] + 2;
            else
                dp[i][j] = max(dp[i+1][j],dp[i][j-1]);
        }
    }
    cout << dp[0][n-1] << endl;
    return 0;
}

在这里插入图片描述
在这里插入图片描述

4、题目链接

🌟爱丽丝的人偶
🌟集合
🌟最长回文子序列

最长回文子序列(Longest Palindromic Subsequence,LPS)问题是指在一个给定的字符串中找到一个最长回文子序列回文子序列是指一个序列本身不是回文串,但它是一个回文串的子序列。 在C++中,我们可以使用动态规划(Dynamic Programming,DP)的方法来解决这个问题。动态规划的主要思想是将一个大问题分解成小问题,然后从小问题出发,逐渐求得大问题的解。 以下是一个使用动态规划解决最长回文子序列问题的C++示例代码: ```cpp #include <iostream> #include <vector> #include <string> using namespace std; // 函数用于计算字符串str的最长回文子序列的长度 int longestPalindromeSubseq(string str) { int n = str.size(); // 创建一个二维数组dp,用于存储子问题的解,初始化所有值为0 vector<vector<int>> dp(n, vector<int>(n, 0)); // 单个字符的最长回文子序列长度为1,所以对角线上的元素设置为1 for (int i = 0; i < n; i++) { dp[i][i] = 1; } // 如果两个字符相同,那么它俩组成的子序列长度为2 for (int cl = 2; cl <= n; cl++) { for (int i = 0; i < n - cl + 1; i++) { int j = i + cl - 1; if (str[i] == str[j] && cl == 2) { dp[i][j] = 2; } else if (str[i] == str[j]) { dp[i][j] = dp[i + 1][j - 1] + 2; } else { dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]); } } } // 返回整个字符串的最长回文子序列长度 return dp[0][n - 1]; } int main() { string str; cout << "请输入一个字符串:" << endl; cin >> str; cout << "最长回文子序列的长度为:" << longestPalindromeSubseq(str) << endl; return 0; } ``` 在这段代码中,`dp[i][j]`表示从字符串的第`i`个字符到第`j`个字符组成的子串的最长回文子序列的长度。通过初始化对角线以及递推式逐步填充这个二维数组,最终可以得到整个字符串的最长回文子序列长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值