携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
题目
arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。题目要求将数组尽可能多的分块。
方法一:单调栈
思路
看到这题的时候,就想到要用栈的知识来解决。既然块分别排序后连接起来的结果和按升序排序后的原数组相同,那么后面的块中的每个元素都要比前面的块的任意元素大。所以在进行遍历的时候,要将比前一个大的元素push进栈中,如果遇到比前一个元素小的,则需与前面的块合并,以保证顺序。
这样栈中的元素就是数组中每个分块最大的元素,返回栈的长度即可。
代码
var maxChunksToSorted = function(arr) {
let stack = [];
for (let val of arr) {
if (!stack.length || stack[stack.length - 1] <= val) {
stack.push(val);
} else {
let cur = stack.pop();
while (stack.length && stack[stack.length - 1] > val) {
stack.pop();
}
stack.push(cur);
}
}
return stack.length;
}
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
方法二:滑动窗口
思路
这种思路是在题解里看到的,对于这道题来说真的很方便!具体思路是原来的数组分块后,分块的位置与原数组排序后的位置相同,由此我们就可以通过定义两个变量,分别对原数组相加,排序后的数组相加,相加相同即为一个分块。值得注意的是需要考虑数组浅拷贝的问题。
使用sortArr = arr造成数组浅拷贝,由于我们也需要使用原数组,所以不能浅拷贝。
代码
var maxChunksToSorted = function(arr) {
const sortArr = [...arr];
sortArr.sort((a, b) => a - b);
let count = 0,sum1 = 0,sum2 = 0;
for (let i = 0; i < arr.length; i++) {
sum1 += arr[i];
sum2 += sortArr[i];
if (sum1 === sum2) {
count++;
}
}
return count;
}
复杂度
时间复杂度:O(nlogn)
空间复杂度:O(n)