题解 | #合唱队#
合唱队
http://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4
动态规划
这里跟以往不一样的是,需要注意一下上升子序列的定义,这里的子序列可以是间断的,这就加大了这个问题的难度。
我们用动态规划来解决这个问题,定义数组dp,长度与输入数组nums保持一致,dp[i]所代表的含义是以nums[i]结尾的所有上升子序列的最大长度。例如在数组[1, 7, 2, 3, 4, 9]中,[1, 2, 3, 9]为一个到9的上升子序列,[1, 7, 9]也是一个到9的上升子序列,但是前者更长。
定义初始状态,以dp[i](0<=i<len(nums))结尾的所有上升子序列最短是1,也就是只有它本身。
递归关系式:为了求得到达数组中特定位置dp[i]的最长上升子序列的长度,我们需要考虑到在此之前的所有最长上子序列,也就是dp[i]的计算需要依据dp[j](j<=0<i)的计算结果,因此需要两重循环。为了确保子序列是上升的,需要随时判断dp[i]和dp[j]之间的关系。dp[i]的位置随时更新为当前最长子序列的长度。递推关系式为:
dp[i] = max(dp[i], dp[j]+1),条件是 nums[j] < nums[i]
为什么dp[j]+1可以算作到达dp[i]的一个上升子序列的长度?因为当nums[i]<nums[i]时,nums[i]的元素相当于对nums[j]结尾的最长上升子序列的一个扩展。为什么需要取max?因为到达nums[i]的上升子序列不止一个,需要取最长的。
最终结果:由于我们并不知道最长上升子序列在什么位置结尾,因此需要对dp中所有元素取最大值。
作者:玖月晴 链接:https://www.jianshu.com/p/ff887a93437d 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
遗憾的是,经常超时,可能还是需要用二分法做,方式我没看懂
import sys
# 获取最大增长子序列
def get_max_up_sub_arr(count, arr):
up_arr = [1 for x in range(count)]
for i in range(count):
for j in range(i):
if arr[j] < arr[i]:
up_arr[i] = max(up_arr[i], up_arr[j]+1)
return up_arr
while True:
try:
count = int(input())
arr = list(map(int, input().split(' ')))
left_up_arr = get_max_up_sub_arr(count, arr)
right_up_arr = get_max_up_sub_arr(count, arr[::-1])[::-1]
print(count - max(i + j - 1 for i, j in zip(left_up_arr, right_up_arr)))
except EOFError:
break