Taro Logo

Find the Maximum Length of Valid Subsequence II

Medium
Meta logo
Meta
8 views
Topics:
ArraysDynamic Programming

You are given an integer array nums and a positive integer k. A subsequence sub of nums with length x is called valid if it satisfies: (sub[0] + sub[1]) % k == (sub[1] + sub[2]) % k == ... == (sub[x - 2] + sub[x - 1]) % k. Return the length of the longest valid subsequence of nums.

Example 1:

nums = [1,2,3,4,5], k = 2

Output: 5

Explanation: The longest valid subsequence is [1, 2, 3, 4, 5].

Example 2:

nums = [1,4,2,3,1,4], k = 3

Output: 4

Explanation: The longest valid subsequence is [1, 4, 1, 4].

Can you write a function to solve this problem efficiently?

Solution


Brute Force Approach

A brute-force approach would involve generating all possible subsequences of the given array nums and then checking each subsequence for validity according to the specified condition. The longest valid subsequence's length would then be returned.

Algorithm

  1. Generate all possible subsequences of nums.
  2. For each subsequence, check if it's valid.
  3. If a subsequence is valid, compare its length with the current maximum length found so far.
  4. Return the maximum length.

Code (Python)

def is_valid(sub, k):
    if len(sub) < 2:
        return True
    rem = (sub[0] + sub[1]) % k
    for i in range(1, len(sub) - 1):
        if (sub[i] + sub[i+1]) % k != rem:
            return False
    return True

def longest_valid_subsequence_brute_force(nums, k):
    max_len = 0
    for i in range(1 << len(nums)):
        sub = []
        for j in range(len(nums)):
            if (i >> j) & 1:
                sub.append(nums[j])
        if is_valid(sub, k):
            max_len = max(max_len, len(sub))
    return max_len

Time Complexity

The time complexity of this brute-force approach is O(2n * n), where n is the length of nums. This is because there are 2n possible subsequences, and checking the validity of each subsequence takes O(n) time.

Space Complexity

The space complexity is O(n) in the worst case, as the longest subsequence can be of length n.

Optimal Approach

The key observation is that for a subsequence to be valid, the value of (nums[i] + nums[i+1]) % k must be the same for all consecutive pairs in the subsequence. This means nums[i] % k + nums[i+1] % k must be the same modulo k. Thus, nums[i] % k - nums[i+2] % k must be equal modulo k, thus nums[i] % k == nums[i+2] % k. So all elements at even index positions, and all element at odd index positions must have the same remainders when divided by k. Thus the longest valid subsequence has length count_even + count_odd where each count is the number of array elements with a certain remainder modulo k.

Algorithm

  1. Create a dictionary to store the count of each remainder when nums[i] is divided by k.
  2. Iterate through nums and update the counts in the dictionary.
  3. Find the two largest counts in the dictionary.
  4. Return the sum of the two largest counts.

Code (Python)

def longest_valid_subsequence(nums, k):
    counts = {}
    for num in nums:
        remainder = num % k
        counts[remainder] = counts.get(remainder, 0) + 1
    
    if len(counts) == 0:
        return 0

    if len(counts) == 1:
        return list(counts.values())[0]

    
    sorted_counts = sorted(counts.values(), reverse=True)
    return sorted_counts[0] + sorted_counts[1] if len(sorted_counts) > 1 else sorted_counts[0]

Time Complexity

The time complexity of this optimal approach is O(n), where n is the length of nums. This is because we iterate through nums once to calculate the counts.

Space Complexity

The space complexity is O(k), where k is the value given. In the worst case, all elements have different remainders when divided by k.

Edge Cases

  • If nums is empty, return 0.
  • If k is 1, all numbers have the same remainder of 0. So the answer is len(nums).