Skip to main content

Find the Maximum Length of a Good Subsequence II - Solution & Explanation

HardArrayHash TableDynamic Programming23 min readAsked at: Snowflake
Practice this problem

Problem Statement

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 <= 5 * 103
  • 1 <= nums[i] <= 109
  • 0 <= k <= min(50, nums.length)

Approach Overview

Problem Overview: You are given an integer array and a limit k. A subsequence is considered good if the number of positions where adjacent elements differ is at most k. The task is to select a subsequence with the maximum possible length while keeping the number of value transitions ≤ k.

Approach 1: Sliding Window with Transition Count (O(n) time, O(1) space)

This approach treats the problem similarly to a longest valid segment problem. Iterate through the array using two pointers and track how many times adjacent values change inside the current window. When the transition count exceeds k, move the left pointer forward and update the count. The window length represents the current candidate subsequence length. The key operation is maintaining a running count of value changes while expanding and shrinking the window. This works well when the optimal subsequence closely follows the original order and you want a linear-time scan.

Approach 2: Greedy with Frequency Count (O(n) time, O(m) space)

Another practical strategy maintains frequency counts of elements inside the current window using a hash table. Track the most frequent value and compare it with the window length. If too many elements differ from the dominant value, shrink the window. The idea is similar to problems where you keep the majority element and allow limited deviations. Each step performs constant-time updates to the frequency map and adjusts the window boundaries. This greedy strategy works well when the optimal subsequence tends to cluster around frequently appearing values.

Approach 3: Dynamic Programming with Hash Maps (O(nk) time, O(nk) space)

The most general solution uses dynamic programming. Maintain dp[v][c], the maximum length of a subsequence ending with value v using exactly c transitions. When processing each element, you can either extend a subsequence ending with the same value (no new transition) or extend the best subsequence with c-1 transitions and switch values. A global array keeps track of the best subsequence length for each transition count so updates stay efficient. Hash maps store states for values that appear, avoiding large fixed arrays. Each iteration updates states for all k transition levels.

Recommended for interviews: The dynamic programming approach is typically what interviewers expect. It clearly models the subsequence constraint and handles arbitrary value patterns. Sliding window and greedy techniques are useful for reasoning about local segments, but the DP formulation demonstrates deeper understanding of subsequence transitions and state optimization using array iteration and hash-based state tracking.

Approach 1: Sliding Window Approach

This approach uses the sliding window technique to find the maximum length of a good subsequence. The aim is to maintain a window that can have at most k differences between consecutive elements.

The technique involves two pointers, one representing the start of the window and the other the end, iterating through the array and counting differences. If the differences exceed k, the start pointer is moved forward to reduce the count.

This solution in C initializes two pointers i and j. The pointer j expands the window while counting the number of differences between consecutive elements. If the count exceeds k, the window is shrunk from the left by incrementing i.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n), where n is the length of the array. Space Complexity: O(1) as no extra space is used beyond variables.

Try this approach in the editor →

Approach 2: Greedy Approach with Frequency Count

This approach involves counting the frequency of each number in the array. The idea is to use the most frequent numbers to form the longest possible good subsequence, allowing up to k unique transitions where necessary.

By first counting the frequencies and then iterating over the sorted frequency list, we can focus on building the longest possible sequence that satisfies the conditions.

This C implementation uses a frequency array to count occurrences of each number. Frequencies are sorted in descending order, and the algorithm selects most frequent numbers up to k times, summing their counts to get the maximum possible length of the subsequence.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n + n log n) due to sorting, where n is the number of elements. Space Complexity: O(n) for the frequency count array.

Try this approach in the editor →

Approach 3: Dynamic Programming

We define f[i][h] as the length of the longest good subsequence ending with nums[i] and having no more than h indices satisfying the condition. Initially, f[i][h] = 1. The answer is max(f[i][k]), where 0 \le i < n.

We consider how to calculate f[i][h]. We can enumerate 0 \le j < i, if nums[i] = nums[j], then f[i][h] = max(f[i][h], f[j][h] + 1); otherwise, if h > 0, then f[i][h] = max(f[i][h], f[j][h - 1] + 1). That is:

$ f[i][h]= \begin{cases} max(f[i][h], f[j][h] + 1), & if nums[i] = nums[j], \ max(f[i][h], f[j][h - 1] + 1), & if h > 0. \end{cases}

The final answer is max(f[i][k]), where 0 \le i < n.

The time complexity is O(n^2 times k), and the space complexity is O(n times k). Where n is the length of the array nums.

Due to the large data range of this problem, the above solution will time out and needs to be optimized.

According to the state transition equation, if nums[i] = nums[j], then we only need to get the maximum value of f[j][h], we can maintain it with an array mp of length k + 1. If nums[i] neq nums[j], we need to record the maximum value of f[j][h - 1] corresponding to nums[j], the maximum value and the second maximum value, we can maintain it with an array g of length k + 1.

The time complexity is O(n times k), and the space complexity is O(n times k). Where n$ is the length of the array nums.

Code

Python

Java

C++

Go

TypeScript

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Sliding Window Approach

Time Complexity: O(n), where n is the length of the array. Space Complexity: O(1) as no extra space is used beyond variables.

Greedy Approach with Frequency Count

Time Complexity: O(n + n log n) due to sorting, where n is the number of elements. Space Complexity: O(n) for the frequency count array.

Dynamic Programming—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Sliding Window with Transition CountO(n)O(1)When treating the problem as a longest valid contiguous segment with limited value changes
Greedy with Frequency CountO(n)O(m)When frequent values dominate the sequence and a majority-based window works well
Dynamic Programming with Hash MapsO(nk)O(nk)General solution for subsequences with up to k transitions

Video Solution

3177 & 3176 Find the Maximum Length of a Good Subsequence II & Subsequence I I | DP | LIS • Aryan Mittal • 8,770 views views

Watch 7 more video solutions →

Frequently Asked Questions

Is Find the Maximum Length of a Good Subsequence II easy or hard?
The problem is rated Hard because it requires designing a multi-dimensional dynamic programming state and optimizing transitions efficiently. Handling subsequences rather than contiguous segments makes the reasoning more complex than typical sliding window problems.
Find the Maximum Length of a Good Subsequence II Python/Java solution
Most solutions iterate through the array and update dynamic programming states. Python implementations typically use dictionaries for dp[value][changes], while Java versions use HashMap structures or arrays when the value range is small. Both achieve O(nk) time complexity.
How to solve Find the Maximum Length of a Good Subsequence II in O(n)?
A linear-time heuristic uses a sliding window with frequency counting. Maintain a window, track element frequencies with a hash table, and keep the window valid while the number of differing elements stays within k. Each element enters and leaves the window at most once, giving O(n) time.
What is the best approach for Find the Maximum Length of a Good Subsequence II?
The most reliable approach uses dynamic programming. Track the longest subsequence ending with each value while counting how many value transitions have been used. The DP state dp[value][changes] is updated while scanning the array, giving an O(nk) time solution that handles arbitrary value distributions.
Is Find the Maximum Length of a Good Subsequence II asked at Google/Amazon/Meta?
Problems involving subsequence dynamic programming and transition counting appear frequently in interviews at companies like Google, Amazon, and Meta. Variants of this problem test DP state design, hash map optimization, and reasoning about sequence transitions.
What data structure is used in Find the Maximum Length of a Good Subsequence II?
Common implementations use hash tables to store subsequence states by value and dynamic programming arrays indexed by transition count. Sliding window approaches also rely on hash maps to track element frequencies inside the current window.
What is the time complexity of Find the Maximum Length of a Good Subsequence II?
The optimal dynamic programming solution runs in O(nk) time where n is the array length and k is the maximum allowed number of value changes. Each element updates states for all transition counts from 0 to k. Space complexity is also O(nk) when storing subsequence lengths for each value and transition level.

Ready to solve this problem?

Practice Find the Maximum Length of a Good Subsequence II with our built-in code editor and test cases.

Practice on FleetCode