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,\dots]$满足$(a_1+b_1)% k == (b_1+a_2)%k == (a_2+b2)%k==\dots$的话,则有:

$a_1, a_2,\dots$对$k$同余,$b_1,b_2,\dots$对$k$同余。

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

使用一个动态规划数组$dp[i][j]$代表$a_*$模$k$等于$i$而$b_*$模$k$等于$j$的$[a_1,b_1,a_2,b_2\dots]$序列的最大长度,则可以:

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

$dp[y][x]=dp[x][y]+1$

注意,$dp[a][b]$代表的$abab$序列,结尾一定是$b$,但开头不一定是$a$(可以是$abab$也可以是$babab$)。

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

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
* @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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'''
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* @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和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


3202.找出有效子序列的最大长度 II:取模性质(动态规划)
https://blog.letmefly.xyz/2025/07/20/LeetCode 3202.找出有效子序列的最大长度II/
作者
发布于
2025年7月20日
许可协议