📅  最后修改于: 2023-12-03 15:42:03.435000             🧑  作者: Mango
给定一个长度为n的数组arr,通过改变数组arr中两端的元素,使得该数组的最长非递减子序列长度最大化。
动态规划
该问题可以转化为一个最长上升子序列问题,具体做法如下:
数组 arr
,数组长度 n
。dp
用来记录到达 i
位置时的最长非递减子序列长度。dp[i]=1
(每个元素本身都是一个非递减子序列)。i=1
到 n-1
依次遍历,对于每个 arr[i]
,从 j=0
到 i-1
依次遍历,当 arr[j] <= arr[i]
时,更新 dp[i] = max(dp[i], dp[j] + 1)
。dp
中的最大值。这个做法的时间复杂度为 $O(n^2)$,需要优化。可以通过使用二分查找进行优化。
二分查找+贪心
该方法利用了二分查找和贪心思想,具体做法如下:
数组 arr
,数组长度 n
。dp
用来记录到达 i
位置时的最长递增子序列长度。len=1
,和数组 d
保存长度为 len
的最长递增子序列的末尾元素。arr
的每个位置 i
,在 d
数组中查找第一个大于等于 arr[i]
的位置 k
,再将 arr[i]
赋值给 d[k]
,更新 dp[i]=k+1
。arr[i] > d[len]
,说明 arr[i]
可以接在最长递增子序列的后面,更新 len = len + 1
,并将 arr[i]
放到 d
数组最后。dp
的最大值。该方法的时间复杂度为 $O(n\log n)$。
def max_increase_length(arr, n):
dp = [1] * n
for i in range(1, n):
for j in range(i):
if arr[j] <= arr[i]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)
import bisect
def max_increase_length(arr, n):
d = [arr[0]]
dp = [1] * n
for i in range(1, n):
if arr[i] > d[-1]:
d.append(arr[i])
dp[i] = len(d)
else:
k = bisect.bisect_left(d, arr[i])
d[k] = arr[i]
dp[i] = k + 1
return max(dp)
本文介绍了两种求解最长非递减子序列的算法,并给出了相应的代码实现。其中,方法二基于二分查找和贪心思想,时间复杂度较小,建议在实际开发中使用。