LeetCode 题解工作台

找出有效子序列的最大长度 II

给你一个整数数组 nums 和一个 正 整数 k 。 nums 的一个 子序列 sub 的长度为 x ,如果其满足以下条件,则称其为 有效子序列 : (sub[0] + sub[1]) % k == (sub[1] + sub[2]) % k == ... == (sub[x - 2] + sub[…

category

2

题型

code_blocks

7

代码语言

hub

3

相关题

当前训练重点

中等 · 状态·转移·动态规划

bolt

答案摘要

根据题目描述,我们可以得知,对于子序列 $a_1, a_2, a_3, \cdots, a_x$,如果满足 $(a_1 + a_2) \bmod k = (a_2 + a_3) \bmod k$。那么 $a_1 \bmod k = a_3 \bmod k$。也即是说,所有奇数项元素对 取模的结果相同,所有偶数项元素对 取模的结果相同。 我们可以使用动态规划的方法解决这个问题。定义状态 表示最…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个整数数组 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
lightbulb

解题思路

方法一:动态规划

根据题目描述,我们可以得知,对于子序列 a1,a2,a3,,axa_1, a_2, a_3, \cdots, a_x,如果满足 (a1+a2)modk=(a2+a3)modk(a_1 + a_2) \bmod k = (a_2 + a_3) \bmod k。那么 a1modk=a3modka_1 \bmod k = a_3 \bmod k。也即是说,所有奇数项元素对 kk 取模的结果相同,所有偶数项元素对 kk 取模的结果相同。

我们可以使用动态规划的方法解决这个问题。定义状态 f[x][y]f[x][y] 表示最后一项对 kk 取模为 xx,倒数第二项对 kk 取模为 yy 的最长有效子序列的长度。初始时 f[x][y]=0f[x][y] = 0

遍历数组 numsnums,对于每一个数 xx,我们得到 x=xmodkx = x \bmod k。然后我们可以枚举序列连续两个数对 jj 取模结果相同,其中 j[0,k)j \in [0, k)。那么 xx 的前一个数对 kk 取模结果为 y=(jx+k)modky = (j - x + k) \bmod k。此时 f[x][y]=f[y][x]+1f[x][y] = f[y][x] + 1

答案为所有 f[x][y]f[x][y] 中的最大值。

时间复杂度 O(n×k)O(n \times k),空间复杂度 O(k2)O(k^2)。其中 nn 为数组 nums\textit{nums} 的长度,而 kk 为给定的正整数。

Python3

class Solution:
    def maximumLength(self, nums: List[int], k: int) -> int:
        f = [[0] * k for _ in range(k)]
        ans = 0
        for x in nums:
            x %= k
            for j in range(k):
                y = (j - x + k) % k
                f[x][y] = f[y][x] + 1
                ans = max(ans, f[x][y])
        return ans

Java

class Solution {
    public int maximumLength(int[] nums, int k) {
        int[][] f = new int[k][k];
        int ans = 0;
        for (int x : nums) {
            x %= k;
            for (int j = 0; j < k; ++j) {
                int y = (j - x + k) % k;
                f[x][y] = f[y][x] + 1;
                ans = Math.max(ans, f[x][y]);
            }
        }
        return ans;
    }
}

C++

class Solution {
public:
    int maximumLength(vector<int>& nums, int k) {
        int f[k][k];
        memset(f, 0, sizeof(f));
        int ans = 0;
        for (int x : nums) {
            x %= k;
            for (int j = 0; j < k; ++j) {
                int y = (j - x + k) % k;
                f[x][y] = f[y][x] + 1;
                ans = max(ans, f[x][y]);
            }
        }
        return ans;
    }
};

Go

func maximumLength(nums []int, k int) (ans int) {
	f := make([][]int, k)
	for i := range f {
		f[i] = make([]int, k)
	}
	for _, x := range nums {
		x %= k
		for j := 0; j < k; j++ {
			y := (j - x + k) % k
			f[x][y] = f[y][x] + 1
			ans = max(ans, f[x][y])
		}
	}
	return
}

TypeScript

function maximumLength(nums: number[], k: number): number {
    const f: number[][] = Array.from({ length: k }, () => Array(k).fill(0));
    let ans: number = 0;
    for (let x of nums) {
        x %= k;
        for (let j = 0; j < k; ++j) {
            const y = (j - x + k) % k;
            f[x][y] = f[y][x] + 1;
            ans = Math.max(ans, f[x][y]);
        }
    }
    return ans;
}

Rust

impl Solution {
    pub fn maximum_length(nums: Vec<i32>, k: i32) -> i32 {
        let k = k as usize;
        let mut f = vec![vec![0; k]; k];
        let mut ans = 0;
        for x in nums {
            let x = (x % k as i32) as usize;
            for j in 0..k {
                let y = (j + k - x) % k;
                f[x][y] = f[y][x] + 1;
                ans = ans.max(f[x][y]);
            }
        }
        ans
    }
}

C#

public class Solution {
    public int MaximumLength(int[] nums, int k) {
        int[,] f = new int[k, k];
        int ans = 0;
        foreach (int num in nums) {
            int x = num % k;
            for (int j = 0; j < k; ++j) {
                int y = (j - x + k) % k;
                f[x, y] = f[y, x] + 1;
                ans = Math.Max(ans, f[x, y]);
            }
        }
        return ans;
    }
}
speed

复杂度分析

指标
时间complexity is O(n \times k) since each element is compared against k possible modulo states. Space complexity is O(k^2) to maintain DP tables for all modulo combinations efficiently.
空间O(k^2)
psychology

面试官常问的追问

外企场景
  • question_mark

    Are you considering the correct state space for DP transitions with modulo constraints?

  • question_mark

    Can you optimize memory usage by storing only necessary DP states?

  • question_mark

    Have you correctly handled the subsequence selection without breaking the original array order?

warning

常见陷阱

外企场景
  • error

    Forgetting to fix the initial modulo value, which can lead to incorrect subsequence validation.

  • error

    Incorrectly assuming contiguous subsequences instead of true subsequences preserving order.

  • error

    Updating DP states without checking if the modulo constraint is maintained, causing invalid subsequences.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Find maximum length subsequence where the sum of every three consecutive elements modulo k is consistent.

  • arrow_right_alt

    Compute maximum length valid subsequence with alternating modulo conditions for even and odd indices.

  • arrow_right_alt

    Determine longest valid subsequence when elements must satisfy a sum modulo constraint with a moving window of size 2.

help

常见问题

外企场景

找出有效子序列的最大长度 II题解:状态·转移·动态规划 | LeetCode #3202 中等