返回

不简单的递增子序列:逐层攻破动态规划的经典习题

后端

题目

给定一个长度为n的整数数组nums,求出其中最长的递增子序列的长度。

题目整理

  • 输入:一个长度为n的整数数组nums。
  • 输出:其中最长的递增子序列的长度。

解题思路

最长递增子序列问题是一个典型的动态规划问题。我们可以通过建立一个子问题状态表,将大问题分解成若干个相互关联的小问题,然后根据子问题的解来求得整个问题的解。

子问题状态表中每个单元格dp[i]表示以下标i结尾的最长递增子序列的长度。那么,dp[i]可以由如下递推公式求得:

dp[i] = max(dp[j] + 1)

其中,j < i且nums[j] < nums[i]。

具体实现

// 动态规划算法求最长递增子序列的长度
int longest_increasing_subsequence(vector<int>& nums) {
  // 创建子问题状态表
  vector<int> dp(nums.size(), 1);

  // 逐个计算子问题的解
  for (int i = 1; i < nums.size(); i++) {
    for (int j = 0; j < i; j++) {
      if (nums[j] < nums[i]) {
        dp[i] = max(dp[i], dp[j] + 1);
      }
    }
  }

  // 返回最终的解
  return *max_element(dp.begin(), dp.end());
}

代码示例

#include <iostream>
#include <vector>

using namespace std;

int longest_increasing_subsequence(vector<int>& nums) {
  // 创建子问题状态表
  vector<int> dp(nums.size(), 1);

  // 逐个计算子问题的解
  for (int i = 1; i < nums.size(); i++) {
    for (int j = 0; j < i; j++) {
      if (nums[j] < nums[i]) {
        dp[i] = max(dp[i], dp[j] + 1);
      }
    }
  }

  // 返回最终的解
  return *max_element(dp.begin(), dp.end());
}

int main() {
  vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  int length = longest_increasing_subsequence(nums);

  cout << "最长递增子序列的长度为:" << length << endl;

  return 0;
}

输出结果:

最长递增子序列的长度为:10

总结

最长递增子序列问题是一个典型的动态规划问题。通过建立子问题状态表,我们可以将大问题分解成若干个相互关联的小问题,然后根据子问题的解来求得整个问题的解。在本文中,我们详细介绍了如何使用动态规划算法来解决最长递增子序列问题,并给出了具体的实现和代码示例。