求出最长好子序列I

2024-09-06

题目:

给你一个整数数组 nums 和一个 非负 整数 k 。如果一个整数序列 seq 满足在范围下标范围 [0, seq.length - 2] 中存在 不超过 k 个下标 i 满足 seq[i] != seq[i + 1] ,那么我们称这个整数序列为 序列。请你返回 nums 子序列的最长长度

示例 1:

输入:nums = [1,2,1,1,3], k = 2

输出:4

解释:

最长好子序列为 [1,2,1,1,3]

示例 2:

输入:nums = [1,2,3,4,5,1], k = 0

输出:2

解释:

最长好子序列为 [1,2,3,4,5,1]

提示:

  • 1 <= nums.length <= 500
  • 1 <= nums[i] <= 109
  • 0 <= k <= min(nums.length, 25)

思路:

很容易想到用 dp[i][j] 来表示以 nums[i] 结尾组成的最长合法序列中有 j 个数字与其在序列中的后一个数字不相等。其中 i 的取值为 nums 的长度,j 不超过 k。初始时,有 dp[i][0] = 1。对于转移,可以枚举每一个满足 x<i 的下标,有:
	dp[i][j] = max j dp[x][j − (nums[x] != nums[i])] + 1

代码:

class Solution {
public:
    int maximumLength(vector<int>& nums, int k) {
        int ans = 0;
        int len = nums.size();
        vector<vector<int>> dp;
        dp.resize(len, vector<int>(51, -1));

        for (int i = 0; i < len; i++) {
            dp[i][0] = 1;
            for (int l = 0; l <= k; l++) {
                for (int j = 0; j < i; j++) {
                    int add = (nums[i] != nums[j]);
                    if (l - add >= 0 && dp[j][l - add] != -1) {
                        dp[i][l] = max(dp[i][l], dp[j][l - add] + 1);
                    }
                }
                ans = max(ans, dp[i][l]);
            }
        }

        return ans;
    }
};