目录
一、题目
1、题目描述
给你一个整数数组
nums
和一个 非负 整数k
。如果一个整数序列seq
满足在范围下标范围[0, seq.length - 2]
中存在 不超过k
个下标i
满足seq[i] != seq[i + 1]
,那么我们称这个整数序列为 好 序列。请你返回
nums
中 好子序列
的最长长度
2、接口描述
python3
python
class Solution:
def maximumLength(self, nums: List[int], k: int) -> int:
cpp
cpp
class Solution {
public:
int maximumLength(vector<int>& nums, int k) {
}
};
C#
cs
public class Solution {
public int MaximumLength(int[] nums, int k) {
}
}
3、原题链接
二、解题报告
1、思路分析
很容易想到状态定义:
f(x, j) 为 以x结尾有 j 个 坏pair 的最大好序列长度
那么有转移方程:
f(x, j) = f(y, j - 1) + 1,y != x
f(x, j) = f(x, j) + 1
每次从当前列或者左边列转移,我们考虑前缀优化
ma[j + 1] 代表 第 j 列最大值
那么 f(i, j) = max(f(i, j), ma(j)) + 1
ma(j) 可能会包含 f(x, j - 1),但是由于 f(x, j) >= f(x, j - 1),所以f(x, j) + 1 >= f(x, j - 1) + 1,不影响状态转移的正确性
2、复杂度
时间复杂度: O(NK)空间复杂度:O(NK)
3、代码详解
python3
python
class Solution:
def maximumLength(self, nums: list[int], k: int) -> int:
f = defaultdict(list)
ma = [0] * (k + 2)
for x in nums:
if x not in f:
f[x] = [0] * (k + 1)
nf = f[x]
for j in range(k, -1, -1):
nf[j] = max(nf[j], ma[j]) + 1
ma[j + 1] = max(ma[j + 1], nf[j])
return ma[-1]
cpp
cpp
class Solution {
public:
int maximumLength(vector<int>& nums, int k) {
std::unordered_map<int, std::vector<int>> f;
std::vector<int> ma(k + 2);
for (int x : nums) {
for (int j = k; ~j; -- j) {
if (!f.contains(x)) f[x] = std::vector<int>(k + 1);
auto &nf = f[x];
nf[j] = std::max(nf[j], ma[j]) + 1;
ma[j + 1] = std::max(nf[j], ma[j + 1]);
}
}
return ma.back();
}
};
C#
cs
public class Solution {
public int MaximumLength(int[] nums, int k) {
int n = nums.Length;
int[] ma = new int[k + 2]; // column max
IDictionary<int, int[]> f = new Dictionary<int, int[]>();
foreach(int x in nums) {
if (!f.ContainsKey(x))
f.Add(x, new int[k + 1]);
var nf = f[x];
for (int j = k; j >= 0; -- j) {
nf[j] = Math.Max(nf[j], ma[j]) + 1;
ma[j + 1] = Math.Max(ma[j + 1], nf[j]);
}
}
return ma[^1];
}
}