前缀和优化DP,LeetCode 3177. 求出最长好子序列 II

目录

一、题目

1、题目描述

2、接口描述

python3

cpp

C#

3、原题链接

二、解题报告

1、思路分析

2、复杂度

3、代码详解

python3

cpp

C#


一、题目

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、原题链接

3177. 求出最长好子序列 II


二、解题报告

1、思路分析

很容易想到状态定义:

f(x, j) 为 以x结尾有 j 个 坏pair 的最大好序列长度

那么有转移方程:

f(x, j) = f(y, j - 1) + 1,y != x

f(x, j) = f(x, j) + 1

每次从当前列或者左边列转移,我们考虑前缀优化

maj + 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];
    }
}
相关推荐
退休倒计时2 分钟前
【每日一题】LeetCode 88. 合并两个有序数组 TypeScript
算法·leetcode·职场和发展·typescript
键盘会跳舞8 分钟前
C++:函数对象与 std::function 源码级深度拆解——泛型算法的策略内核与可调用对象统一封装
c++·算法·仿函数
手写码匠13 分钟前
华为云Flexus+DeepSeek征文|Agent 评测体系实战:用 DeepSeek-R1 当裁判,打造 Dify Agent 的自动化回归测试流水线
人工智能·深度学习·算法·aigc
LONGZETECH24 分钟前
无人机实训高成本痛点解法:虚拟仿真实现 70% 耗材损耗下降
大数据·算法·unity·架构·无人机
不会就选b28 分钟前
算法日常・每日刷题--<队列,宽搜>4
算法
码字的特恩41 分钟前
微软确认暂不为 Windows 11 加入透明效果自定义功能,建议用户使用第三方工具
人工智能·windows·算法·microsoft·计算机·大模型·编程
星轨初途1 小时前
LeetCode 热题 100——day10 和为 K 的子数组
开发语言·c++·算法·leetcode
数模竞赛Paid answer1 小时前
2021年深圳杯数学建模C题配电网可靠性和故障软自愈研究解题全过程论文及程序
算法·数学建模·数据分析·深圳杯
有点。1 小时前
C++广度优先搜索(二)-练习题
c++·算法·宽度优先
疯狂打码的少年1 小时前
【数据结构】队列的应用:循环队列
数据结构·笔记·算法