最多能完成排序的块(力扣第769题)
769. 最多能完成排序的块
数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。我们最多能将数组分成多少块?
示例 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] 可以得到最多的块数。
注意:
arr的长度在 [1, 10] 之间。arr[i]是 [0, 1, ..., arr.length - 1]的一种排列。
分析:
给定的数组的元素值的取值范围是0n-1;数组的索引范围也是0n-1;数组升序排序后,则索引值和元素值是相等的。对于原始的无序数组,要想分块排序然后各块连接之后与整体排序相同,那么分块的时候,每个块所包含的元素与包含的原始数组中的索引必须是一致的,比如划分的某个块,包含的元素值有2、3、4,那么这个块所包含的原始数组中的索引也应该只有2、3、4这几个,只有这样才能保证分块排序然后进行连接与整体升序排序的结果相同。
那么如何划分块呢?
首先从第一个元素开始遍历,寻找当前已经访问的元素中的最大值,如果该最大值等于当前正在访问的元素索引,那么该索引及其之前的索引对应的元素就可以划分为一块;然后继续遍历,直到全部访问结束。我们可以知道,对于原始数组中的元素,如果某个元素值与索引值相同,同时它之前的元素中没有比它大的,那么这个元素就可以单独划分为一块,否则是无法单独划分为一块的,因为一旦它单独划分为一块,那么前面比它大的元素无法再和它相匹配的索引值划分到一组的,那么也就无法达到最终的要求。
代码
public int maxChunksToSorted(int[] arr) {
if (arr == null || arr.length == 0){
return 0;
}
int curMax = arr[0];
int res = 0;
for (int i = 0; i < arr.length; i++) {
if (curMax < arr[i]){
curMax = arr[i];
}
if (curMax == i){
res++;
}
}
return res;
}