You are given an array of integers nums
. Find the length of the longest subsequence seq
of nums
, such that the absolute differences between consecutive elements form a non-increasing sequence of integers.
In other words, for a subsequence seq₀
, seq₁
, seq₂
, ..., seqₘ
of nums
, |seq₁ - seq₀| >= |seq₂ - seq₁| >= ... >= |seqₘ - seqₘ₋₁|
.
Return the length of such a subsequence.
Example 1:
Input: nums = [16,6,3]
Output: 3
Explanation: The longest subsequence is [16, 6, 3]
with absolute adjacent differences [10, 3]
.
Example 2:
Input: nums = [6,5,3,4,2,1]
Output: 4
Explanation: The longest subsequence is [6, 4, 2, 1]
with absolute adjacent differences [2, 2, 1]
.
Example 3:
Input: nums = [10,20,10,19,10,20]
Output: 5
Explanation: The longest subsequence is [10, 20, 10, 19, 10]
with absolute adjacent differences [10, 10, 9, 9]
.
Constraints:
2 <= nums.length <= 10⁴
1 <= nums[i] <= 300
A brute force solution would involve generating all possible subsequences of the given array nums
, and then checking if each subsequence satisfies the non-increasing absolute difference condition. We would keep track of the longest valid subsequence found so far.
nums
.def is_non_increasing(arr):
for i in range(len(arr) - 1):
if arr[i] < arr[i+1]:
return False
return True
def longest_non_increasing_subsequence_brute_force(nums):
max_len = 0
for i in range(1 << len(nums)):
subsequence = []
for j in range(len(nums)):
if (i >> j) & 1:
subsequence.append(nums[j])
if len(subsequence) < 2:
max_len = max(max_len, len(subsequence))
continue
diffs = []
for k in range(len(subsequence) - 1):
diffs.append(abs(subsequence[k+1] - subsequence[k]))
if is_non_increasing(diffs):
max_len = max(max_len, len(subsequence))
return max_len
# Example usage:
nums = [6, 5, 3, 4, 2, 1]
print(longest_non_increasing_subsequence_brute_force(nums))
nums
.A more efficient solution can be achieved using dynamic programming. We can build a DP table where dp[i]
stores the length of the longest non-increasing subsequence ending at index i
.
dp[i] = 1
for all i
, as a single element is a subsequence of length 1.nums
from i = 1
to n - 1
.i
, iterate from j = 0
to i - 1
.abs(nums[i] - nums[j])
is less than or equal to the minimum absolute difference seen so far for the subsequence ending at j
(or if it's the first element), update dp[i] = max(dp[i], dp[j] + 1)
.def longest_non_increasing_subsequence_dp(nums):
n = len(nums)
dp = [1] * n
max_len = 1
for i in range(1, n):
for j in range(i):
if len(nums) > 0:
diffs = []
temp_list = [nums[j], nums[i]]
for k in range(len(temp_list) - 1):
diffs.append(abs(temp_list[k+1] - temp_list[k]))
candidate_list = nums[:j+1]
candidate_subsequence = [nums[index] for index in range(len(nums)) if nums[index] in candidate_list]
candidate_diffs = []
if len(candidate_subsequence) > 1:
for index_candidate in range(len(candidate_subsequence) - 1):
candidate_diffs.append(abs(candidate_subsequence[index_candidate+1] - candidate_subsequence[index_candidate]))
if len(candidate_diffs) == 0 or diffs[0] <= min(candidate_diffs):
dp[i] = max(dp[i], dp[j] + 1)
max_len = max(max_len, dp[i])
return max_len
# Example usage:
nums = [6, 5, 3, 4, 2, 1]
print(longest_non_increasing_subsequence_dp(nums))
nums = [10,20,10,19,10,20]
print(longest_non_increasing_subsequence_dp(nums))
The nested loops result in a time complexity of O(n2), where n is the length of nums
.
dp
table.