鱼C论坛

 找回密码
 立即注册
查看: 868|回复: 1

[已解决]用c++解决

[复制链接]
发表于 2023-10-25 18:58:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
*<1> 编程求出数列的所有升或降的最大子序列。如下面数列的解为如下:
      1,20,30,12,3,5,7,4,6,100,11,8
     (1,20,30),(30,12,3),(3,5,7),(7,4),(4,6,100),(100,11,8)。
最佳答案
2023-10-25 18:58:30
这个问题可以通过动态规划来解决。首先,我们定义两个数组:increasing和decreasing,用于记录以每个元素结尾的最长升序子序列和最长降序子序列的长度。

我们可以从左到右遍历给定的数列。对于每个元素,我们可以将其与前面的元素进行比较,以确定是否能够扩展当前的升序或降序子序列。

具体的算法如下:

1. 初始化increasing和decreasing数组,将所有元素的初始值都设为1。
2. 从第二个元素开始遍历数列,对于每个元素arr[ i]:
   a. 从第一个元素开始遍历到arr[ i]之前的元素arr[j],如果arr[ i]大于arr[j],则可以将arr[ i]加入到以arr[j]结尾的升序子序列中,更新increasing[ i]为increasing[j]+1。
   b. 从第一个元素开始遍历到arr[ i]之前的元素arr[j],如果arr[ i]小于arr[j],则可以将arr[ i]加入到以arr[j]结尾的降序子序列中,更新decreasing[ i]为decreasing[j]+1。
3. 找到increasing和decreasing数组中的最大值,记为maxLen。
4. 遍历increasing数组,找到值等于maxLen的元素的索引位置,记为endIndex。
5. 从endIndex开始,倒序遍历increasing数组,找到连续maxLen个值等于maxLen的元素,这就是最长升序子序列。
6. 重复步骤5,但是遍历decreasing数组,找到最长降序子序列。

下面是C++的实现代码:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;

  4. void findMaxSubsequence(const vector<int>& arr) {
  5.     int n = arr.size();
  6.     vector<int> increasing(n, 1);
  7.     vector<int> decreasing(n, 1);

  8.     for (int i = 1; i < n; i++) {
  9.         for (int j = 0; j < i; j++) {
  10.             if (arr[ i] > arr[j]) {
  11.                 increasing[ i] = max(increasing[ i], increasing[j] + 1);
  12.             }
  13.             if (arr[ i] < arr[j]) {
  14.                 decreasing[ i] = max(decreasing[ i], decreasing[j] + 1);
  15.             }
  16.         }
  17.     }

  18.     int maxLen = 0;
  19.     int endIndex = 0;
  20.     for (int i = 0; i < n; i++) {
  21.         if (increasing[ i] > maxLen) {
  22.             maxLen = increasing[ i];
  23.             endIndex = i;
  24.         }
  25.         if (decreasing[ i] > maxLen) {
  26.             maxLen = decreasing[ i];
  27.             endIndex = i;
  28.         }
  29.     }

  30.     cout << "最长升序子序列:";
  31.     for (int i = endIndex; i >= 0; i--) {
  32.         if (increasing[ i] == maxLen) {
  33.             cout << arr[ i] << " ";
  34.             maxLen--;
  35.         }
  36.     }
  37.     cout << endl;

  38.     maxLen = decreasing[endIndex];
  39.     cout << "最长降序子序列:";
  40.     for (int i = endIndex; i >= 0; i--) {
  41.         if (decreasing[ i] == maxLen) {
  42.             cout << arr[ i] << " ";
  43.             maxLen--;
  44.         }
  45.     }
  46.     cout << endl;
  47. }

  48. int main() {
  49.     vector<int> arr = {1, 20, 30, 12, 3, 5, 7, 4, 6, 100, 11, 8};
  50.     findMaxSubsequence(arr);
  51.     return 0;
  52. }
复制代码


这段代码会输出最长升序子序列和最长降序子序列。对于给定的数列 [1, 20, 30, 12, 3, 5, 7, 4, 6, 100, 11, 8],输出结果为:

最长升序子序列:1 20 30
最长降序子序列:30 12 3

希望对你有帮助!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-10-25 18:58:30 | 显示全部楼层    本楼为最佳答案   
这个问题可以通过动态规划来解决。首先,我们定义两个数组:increasing和decreasing,用于记录以每个元素结尾的最长升序子序列和最长降序子序列的长度。

我们可以从左到右遍历给定的数列。对于每个元素,我们可以将其与前面的元素进行比较,以确定是否能够扩展当前的升序或降序子序列。

具体的算法如下:

1. 初始化increasing和decreasing数组,将所有元素的初始值都设为1。
2. 从第二个元素开始遍历数列,对于每个元素arr[ i]:
   a. 从第一个元素开始遍历到arr[ i]之前的元素arr[j],如果arr[ i]大于arr[j],则可以将arr[ i]加入到以arr[j]结尾的升序子序列中,更新increasing[ i]为increasing[j]+1。
   b. 从第一个元素开始遍历到arr[ i]之前的元素arr[j],如果arr[ i]小于arr[j],则可以将arr[ i]加入到以arr[j]结尾的降序子序列中,更新decreasing[ i]为decreasing[j]+1。
3. 找到increasing和decreasing数组中的最大值,记为maxLen。
4. 遍历increasing数组,找到值等于maxLen的元素的索引位置,记为endIndex。
5. 从endIndex开始,倒序遍历increasing数组,找到连续maxLen个值等于maxLen的元素,这就是最长升序子序列。
6. 重复步骤5,但是遍历decreasing数组,找到最长降序子序列。

下面是C++的实现代码:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;

  4. void findMaxSubsequence(const vector<int>& arr) {
  5.     int n = arr.size();
  6.     vector<int> increasing(n, 1);
  7.     vector<int> decreasing(n, 1);

  8.     for (int i = 1; i < n; i++) {
  9.         for (int j = 0; j < i; j++) {
  10.             if (arr[ i] > arr[j]) {
  11.                 increasing[ i] = max(increasing[ i], increasing[j] + 1);
  12.             }
  13.             if (arr[ i] < arr[j]) {
  14.                 decreasing[ i] = max(decreasing[ i], decreasing[j] + 1);
  15.             }
  16.         }
  17.     }

  18.     int maxLen = 0;
  19.     int endIndex = 0;
  20.     for (int i = 0; i < n; i++) {
  21.         if (increasing[ i] > maxLen) {
  22.             maxLen = increasing[ i];
  23.             endIndex = i;
  24.         }
  25.         if (decreasing[ i] > maxLen) {
  26.             maxLen = decreasing[ i];
  27.             endIndex = i;
  28.         }
  29.     }

  30.     cout << "最长升序子序列:";
  31.     for (int i = endIndex; i >= 0; i--) {
  32.         if (increasing[ i] == maxLen) {
  33.             cout << arr[ i] << " ";
  34.             maxLen--;
  35.         }
  36.     }
  37.     cout << endl;

  38.     maxLen = decreasing[endIndex];
  39.     cout << "最长降序子序列:";
  40.     for (int i = endIndex; i >= 0; i--) {
  41.         if (decreasing[ i] == maxLen) {
  42.             cout << arr[ i] << " ";
  43.             maxLen--;
  44.         }
  45.     }
  46.     cout << endl;
  47. }

  48. int main() {
  49.     vector<int> arr = {1, 20, 30, 12, 3, 5, 7, 4, 6, 100, 11, 8};
  50.     findMaxSubsequence(arr);
  51.     return 0;
  52. }
复制代码


这段代码会输出最长升序子序列和最长降序子序列。对于给定的数列 [1, 20, 30, 12, 3, 5, 7, 4, 6, 100, 11, 8],输出结果为:

最长升序子序列:1 20 30
最长降序子序列:30 12 3

希望对你有帮助!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 16:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表