题目
给定一个长度为 n 的整数数组 arr ,它表示在 [0, n - 1] 范围内的整数的排列。
我们将 arr 分割成若干 块 (即分区),并对每个块单独排序。将它们连接起来后,使得连接的结果和按升序排序后的原数组相同。
返回数组能分成的最多块数量。
示例
示例 1:
输入: arr = [4,3,2,1,0]
输出: 1
解释: 将数组分成2块或者更多块,都无法得到所需的结果。 例如,分成 [4, 3], [2, 1, 0] 的结果是 [3, 4, 0, 1, 2],这不是有序的数组。
示例 2:
输入: arr = [1,0,2,3,4]
输出: 4
解释: 我们可以把它分成两块,例如 [1, 0], [2, 3, 4]。 然而,分成[1, 0], [2], [3], [4] 可以得到最多的块数。
提示:
n == arr.length
1 <= n <= 10
0 <= arr[i] < n
arr 中每个元素都 不同
思路
动态规划,dp[i]含义为arr到达i这一下标所能符合要求的最大分块数,下面分三种情况讨论状态转移方程:
1.定义一个到达上一个坐标的最大值tmp,若arr[i] > tmp,则说明该值大于前方所有值,可以直接分为一块,dp[i] =
dp[i-1] + 1
2.若arr[i] <tmp,我们应该遍历之前所有遍历过的数,找到最后一个小于arr[i]元素的下标index,判断是否前方是否相对后方元素有序,即判断max(arr[:index+1]) < min(arr[index+1:]), 如果有序,从index到i的dp值都应该改为dp[index] + 1, 如果不是有序,则从index到i的dp值都应该改为1。
题解
class Solution: def maxChunksToSorted(self, arr: List[int]) -> int: tmp, dp = arr[0], [1] * len(arr) for i in range(1,len(arr)): # 第一种情况 if arr[i] > tmp: dp[i] = dp[i-1] + 1 tmp = arr[i] else: index = 1 for j in range(i+1): # 小于且相对有序 if arr[j] < arr[i] and max(arr[:j+1]) < min(arr[j+1:]): # 后方所有元素都改变 index = dp[j] + 1 else: dp[j] = index return dp[-1]