LeetCode 最多能完成排序的块II

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89925661

这个问题和“最多能完成排序的块”相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8。

arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。

我们最多能将数组分成多少块?

示例 1:

输入: arr = [5,4,3,2,1]
输出: 1
解释:
将数组分成2块或者更多块,都无法得到所需的结果。
例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。 

示例 2:

输入: arr = [2,1,3,4,4]
输出: 4
解释:
我们可以把它分成两块,例如 [2, 1], [3, 4, 4]。
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。 

注意:

arr的长度在[1, 2000]之间。
arr[i]的大小在[0, 10**8]之间。

\color{blue}{思路分析:} 这道题和上一题 LeetCode 最多完成排序的块 基本一样,蛋式由于含重复元素并且arr[i]是任意值,所以排序后不是[0, 1, 2, 3, … , n]这种,然而我们在判断index处是否能够切开还是需要判断比arr[index]小的元素是否都出现在index的前面。然而这个问题可以转化一下,我们只要寻找[index + 1, arrSize - 1]这一段是否都比[0, index]这一段的值大,即[0, index]的最大值 < [index + 1, arrSize - 1]最小值注意区间的闭合情况!!!

class Solution {
public:
	int maxChunksToSorted(vector<int>& arr) {
		int arrSize = arr.size(), resCount = 1;
        //leftMax[index]用于记录[0, index]的最大值
        //rightMin[index]用于记录[index + 1, arrSize - 1]的最小值
		vector<int> leftMax(arrSize, 0), rightMin(arrSize, 0);
        //初始化起始值
		leftMax[0] = arr[0];
		rightMin[arrSize - 1] = INT_MAX;
        //第一步:从左到右扫描,递推寻找[0, index]的最大值
		for (int index = 1; index < arrSize; ++index) {
			leftMax[index] = max(arr[index], leftMax[index - 1]);
		}
        //第二步:从右到左扫描,递推寻找[index + 1, arrSize - 1]的最小值
		for (int index = arrSize - 2; index >= 0; --index) {
			rightMin[index] = min(arr[index + 1], rightMin[index + 1]);
		}
		for (int index = 0; index < arrSize - 1; ++index) {
			if (leftMax[index] <= rightMin[index]) {
                //当[0, index]的最大值  < [index + 1, arrSize - 1]最小值时,index就能切开
				resCount += 1;
			}
		}
		return resCount;
	}
};

时间复杂度O(n),额外空间复杂度为O(n).
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/89925661