LeetCode 3202.找出有效子序列的最大长度 II:取模性质(动态规划)

【LetMeFly】3202.找出有效子序列的最大长度 II:取模性质(动态规划)

力扣题目链接:https://leetcode.cn/problems/find-the-maximum-length-of-valid-subsequence-ii/

给你一个整数数组 nums 和一个 正 整数 k 。

nums 的一个 子序列 sub 的长度为 x ,如果其满足以下条件,则称其为 有效子序列 :

  • (sub[0] + sub[1]) % k == (sub[1] + sub[2]) % k == ... == (sub[x - 2] + sub[x - 1]) % k

返回 nums 的 最长 有效子序列 的长度。

示例 1:
**输入:**nums = 1,2,3,4,5, k = 2

**输出:**5

解释:

最长有效子序列是 [1, 2, 3, 4, 5] 。

示例 2:
**输入:**nums = 1,4,2,3,1,4, k = 3

**输出:**4

解释:

最长有效子序列是 [1, 4, 1, 4] 。

提示:

  • 2 <= nums.length <= 103
  • 1 <= nums[i] <= 107
  • 1 <= k <= 103

解题方法:动态规划(DP)

一个序列 a 1 , b 1 , a 2 , b 2 , a 3 , ...   a_1,b_1,a_2,b_2,a_3,\\dots a1,b1,a2,b2,a3,...满足 ( a 1 + b 1 ) % k = = ( b 1 + a 2 ) % k = = ( a 2 + b 2 ) % k = = ... (a_1+b_1)\% k == (b_1+a_2)\%k == (a_2+b2)\%k==\dots (a1+b1)%k==(b1+a2)%k==(a2+b2)%k==...的话,则有:

a 1 , a 2 , ... a_1, a_2,\dots a1,a2,...对 k k k同余, b 1 , b 2 , ... b_1,b_2,\dots b1,b2,...对 k k k同余。

所谓同余,就是模 k k k后的结果相等。

使用一个动态规划数组 d p i j dpij dpij代表 a ∗ a_* a∗模 k k k等于 i i i而 b ∗ b_* b∗模 k k k等于 j j j的 a 1 , b 1 , a 2 , b 2 ...   a_1,b_1,a_2,b_2\\dots a1,b1,a2,b2...序列的最大长度,则可以:

遍历 n u m s nums nums数组,若当前元素(对 k k k取模后)为 x x x,则任何 y x y x yxyx yxyx序列的长度都可以在 x y x y xyxy xyxy序列的基础上再加一个 x x x从而变成 y x y x yxyx yxyx序列。

d p y x = d p x y + 1 dpyx=dpxy+1 dpyx=dpxy+1

注意, d p a b dpab dpab代表的 a b a b abab abab序列,结尾一定是 b b b,但开头不一定是 a a a(可以是 a b a b abab abab也可以是 b a b a b babab babab)。

  • 时间复杂度 O ( O( O(k^2+nk ) ) )
  • 空间复杂度 O ( k 2 ) O(k^2) O(k2)

AC代码

C++
cpp 复制代码
/*
 * @Author: LetMeFly
 * @Date: 2025-07-18 22:33:22
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-07-20 19:32:05
 */
#if defined(_WIN32) || defined(__APPLE__)
#include "_[1,2]toVector.h"
#endif

class Solution {
public:
    int maximumLength(vector<int>& nums, int k) {
        vector<vector<int>> dp(k, vector<int>(k));
        int ans = 0;
        for (int x : nums) {
            x %= k;
            for (int y = 0; y < k; y++) {
                dp[y][x] = dp[x][y] + 1;
                ans = max(ans, dp[y][x]);
            }
        }
        return ans;
    }
};
Python
python 复制代码
'''
Author: LetMeFly
Date: 2025-07-18 22:33:22
LastEditors: LetMeFly.xyz
LastEditTime: 2025-07-20 22:23:43
'''
from typing import List

class Solution:
    def maximumLength(self, nums: List[int], k: int) -> int:
        dp = [[0] * k for _ in range(k)]
        for x in nums:
            x %= k
            for y in range(k):
                dp[y][x] = dp[x][y] + 1
        return max(map(max, dp))
Go
go 复制代码
/*
 * @Author: LetMeFly
 * @Date: 2025-07-18 22:33:22
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-07-20 22:28:07
 */
package main

func maximumLength(nums []int, k int) (ans int) {
    dp := make([][]int, k)
    for i := range dp {
        dp[i] = make([]int, k)
    }
    for _, x := range nums {
        x %= k
        for y := range dp {
            dp[y][x] = dp[x][y] + 1
            ans = max(ans, dp[y][x])
        }
    }
    return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
叼烟扛炮8 分钟前
Linux 学习笔记(六十):单线程的逆袭——epoll 高并发服务器实战
linux·服务器·网络·笔记·学习·算法
careathers1 小时前
【数据结构】基于比较的排序算法 - 交换排序
数据结构·算法·排序算法
文丑颜不良啊1 小时前
LeetCode2081~2100题目解析
java·leetcode
Rabitebla1 小时前
【Linux操作系统】进程篇(十一):进程程序替换——从底层原理到 exec 函数族
linux·服务器·c++·笔记·学习·算法
tellmewhoisi2 小时前
深度学习0:数学知识:正态分布1
人工智能·深度学习·算法
-梅2 小时前
算法(1) 动态规划
算法·动态规划
青少儿编程课堂2 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:Bellman-Ford与SPFA含负权最短路及负环检测全解析
c++·python·算法·bfs·信息学竞赛
文丑颜不良啊2 小时前
LeetCode2061~2080题目解析
java·leetcode
octopus_c3 小时前
STL 之 string:auto 与范围 for、常用接口、模拟实现与深浅拷贝
开发语言·c++·算法
文丑颜不良啊15 小时前
LeetCode1941~1960题目解析
java·leetcode