Find the Maximum Length of a Good Subsequence I
MedPrompt
You are given an integer array nums and a non-negative integer k. A sequence of integers seq is called good if there are at most k indices i in the range [0, seq.length - 2] such that seq[i] != seq[i + 1].
Return the maximum possible length of a good subsequence of nums.
Example 1:
Input: nums = [1,2,1,1,3], k = 2
Output: 4
Explanation:
The maximum length subsequence is [1,2,1,1,3].
Example 2:
Input: nums = [1,2,3,4,5,1], k = 0
Output: 2
Explanation:
The maximum length subsequence is [1,2,3,4,5,1].
Constraints:
1 <= nums.length <= 5001 <= nums[i] <= 1090 <= k <= min(nums.length, 25)
Approaches
2 approaches with complexity analysis and trade-offs.
This approach uses a straightforward dynamic programming solution. We define a 2D DP table, dp[i][j], to store the maximum length of a good subsequence that ends with the element nums[i] and has exactly j mismatches. To compute dp[i][j], we iterate through all previous elements nums[p] (where p < i) and consider extending the subsequences ending at p. This leads to a cubic time complexity relative to the input size and k.
Algorithm
- State Definition: Let
dp[i][j]be the maximum length of a good subsequence that ends with the elementnums[i]and has exactlyjmismatches. - Initialization:
- Create a 2D array
dpof sizen x (k+1), wherenis the length ofnums. - Initialize all entries
dp[i][j]to 1. This represents the base case where the subsequence consists of only the elementnums[i], which has a length of 1 and 0 mismatches.
- Create a 2D array
- Transitions:
- Iterate through the array
numswith indexifrom0ton-1. - For each
i, iterate through all previous indicespfrom0toi-1. - For each pair
(i, p), we consider extending the subsequences that ended atpwith the elementnums[i].- Case 1:
nums[i] == nums[p]- If the current element
nums[i]is the same as the previous elementnums[p], no new mismatch is created. - We can extend any subsequence ending at
pwithjmismatches. The new length will be1 + dp[p][j]. - So, for each
jfrom0tok, we update:dp[i][j] = max(dp[i][j], 1 + dp[p][j]).
- If the current element
- Case 2:
nums[i] != nums[p]- If
nums[i]is different fromnums[p], a new mismatch is created. - We can extend a subsequence ending at
pthat hadj-1mismatches. This is only possible ifj > 0. - The new length will be
1 + dp[p][j-1]. - So, for each
jfrom1tok, we update:dp[i][j] = max(dp[i][j], 1 + dp[p][j-1]).
- If
- Case 1:
- Iterate through the array
- Final Answer:
- The problem asks for the maximum length of a good subsequence with at most
kmismatches. This means we need to find the maximum value in the entiredptable, as any entrydp[i][j]represents a valid good subsequence. - The overall maximum length is the maximum value found in
dpafter all iterations.
- The problem asks for the maximum length of a good subsequence with at most
Walkthrough
The core idea is to build up solutions for subsequences of increasing length. For each element nums[i], we consider it as the potential end of a new, longer subsequence. We look back at all preceding elements nums[p] and see if we can append nums[i] to a subsequence ending at nums[p]. The number of mismatches j is a crucial part of our state, as it determines whether we can append nums[i] if it's different from nums[p]. By systematically building this dp table, we ensure that we have considered all possible valid subsequences.
class Solution { public int maximumLength(int[] nums, int k) { int n = nums.length; // dp[i][j]: max length of a good subsequence ending at index i with j mismatches. int[][] dp = new int[n][k + 1]; int maxLength = 0; for (int i = 0; i < n; i++) { // Initialize dp table for index i. A single element has length 1 and 0 mismatches. for (int j = 0; j <= k; j++) { dp[i][j] = 1; } // Iterate through all previous elements to extend their subsequences. for (int p = 0; p < i; p++) { if (nums[i] == nums[p]) { // No new mismatch. for (int j = 0; j <= k; j++) { dp[i][j] = Math.max(dp[i][j], 1 + dp[p][j]); } } else { // New mismatch is created. for (int j = 1; j <= k; j++) { dp[i][j] = Math.max(dp[i][j], 1 + dp[p][j - 1]); } } } } // The answer is the maximum value in the entire dp table. for (int i = 0; i < n; i++) { for (int j = 0; j <= k; j++) { maxLength = Math.max(maxLength, dp[i][j]); } } return maxLength; }}Complexity
Time
O(n^2 * k), where `n` is the number of elements in `nums`. We have three nested loops: iterating through `i` from `0` to `n-1`, `p` from `0` to `i-1`, and `j` from `0` to `k`.
Space
O(n * k), where `n` is the number of elements in `nums`. This is for the 2D `dp` array.
Trade-offs
Pros
The logic is a direct translation of the problem's recursive structure, making it relatively easy to understand.
It correctly solves the problem and passes within the given constraints.
Cons
The time complexity of
O(n^2 * k)can be slow if the constraints onnwere larger.It is less efficient than the optimized DP approach.
Solutions
Solution
class Solution {public int maximumLength(int[] nums, int k) { int n = nums.length; int[][] f = new int[n][k + 1]; int ans = 0; for (int i = 0; i < n; ++i) { for (int h = 0; h <= k; ++h) { for (int j = 0; j < i; ++j) { if (nums[i] == nums[j]) { f[i][h] = Math.max(f[i][h], f[j][h]); } else if (h > 0) { f[i][h] = Math.max(f[i][h], f[j][h - 1]); } } ++f[i][h]; } ans = Math.max(ans, f[i][k]); } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.