[LeetCode] Max Chunks To Make Sorted II 可排序的最大块数之二
This question is the same as "Max Chunks to Make Sorted" except the integers of the given array are not necessarily distinct, the input array could be up to length 2000, and the elements could be up to 10**8.
Given an array arr of integers (not necessarily distinct), we split the array into some number of "chunks" (partitions), and individually sort each chunk. After concatenating them, the result equals the sorted array.
What is the most number of chunks we could have made?
Example 1:
Input: arr = [5,4,3,2,1]
Output: 1
Explanation:
Splitting into two or more chunks will not return the required result.
For example, splitting into [5, 4], [3, 2, 1] will result in [4, 5, 1, 2, 3], which isn't sorted.
Example 2:
Input: arr = [2,1,3,4,4]
Output: 4
Explanation:
We can split into two chunks, such as [2, 1], [3, 4, 4].
However, splitting into [2, 1], [3], [4], [4] is the highest number of chunks possible.
Note:
arrwill have length in range[1, 2000].arr[i]will be an integer in range[0, 10**8].
这道题是之前那道 Max Chunks To Make Sorted 的拓展,那道题说了数组是[0, n-1]中所有数字的一种全排列,n为数组的长度。而这道题的数字就没有这种限制,可以是大于n的数字,也可以有重复的数字。由于数字和坐标不再有太多的关联,所以之前那题中比较数字和坐标的大小的解法肯定行不通了。我们来看一种十分巧妙的解法,首先我们需要明确的一点是,拆分后的块儿排序后拼在一起会跟原数组相同,我们用一个例子来说明:
2 1 4 3 4
1 2
1 2 3 4 4
我们看到第一行是原数组,第二行是排序后并拼接在了一起的块儿,不同的颜色代表不同的块儿,而第三行是直接对原数组排序后的结果。仔细观察可以发现,能形成块儿的数字之和跟排序后的数组的相同长度的子数组的数字之和是相同的。比如第一个块儿是数字2和1,和为3,而排序后的前两个数字为1和2,和也是3,那么我们就知道原数组的前两个数字可以拆成一个块儿。同理,原数组中的第三个和第四个数字分别为4和3,和为7,而排序后的数组对应位置的数字之和也是7,说明可以拆分出块儿。需要注意的是,在累加数组和的时候有可能会超过整型最大值,所以我们用长整型来保存就可以了。就是这么简单而暴力的思路,时间复杂度为O(nlgn),主要花在给数组排序上了。由于本题是 Max Chunks To Make Sorted 的generalized的情况,所以这种解法自然也可以解决之前那道题了,不过就是时间复杂度稍高了一些,参见代码如下:
解法一:
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
long res = , sum1 = , sum2 = ;
vector<int> expect = arr;
sort(expect.begin(), expect.end());
for (int i = ; i < arr.size(); ++i) {
sum1 += arr[i];
sum2 += expect[i];
if (sum1 == sum2) ++res;
}
return res;
}
};
这道题的时间复杂度可以优化到线性,不过就是需要花点空间。下面这种解法也相当的巧妙,我们需要两个数组forward和backward,其中 foward[i] 表示 [0, i] 范围内最大的数字,而 backward[i] 表示 [i, n-1] 范围内最小的数字,实际上就是要知道已经遍历过的最大值,和还未遍历的到的最小值。为啥我们对这两个值感兴趣呢?这是本解法的精髓所在,我们知道可以拆分为块儿的前提是之后的数字不能比当前块儿中的任何数字小,不然那个较小的数字就无法排到前面。就像例子1,为啥不能拆出新块儿,就因为最小的数字在末尾。那么这里我们能拆出新块儿的条件就是,当前位置出现过的最大值小于等于之后还未遍历到的最小值时,就能拆出新块儿。比如例子2中,当 i=1 时,此时出现过的最大数字为2,未遍历到的数字中最小值为3,所以可以拆出新块儿,参见代码如下:
解法二:
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int res = , n = arr.size();
vector<int> f = arr, b = arr;
for (int i = ; i < n; ++i) f[i] = max(arr[i], f[i - ]);
for (int i = n - ; i >= ; --i) b[i] = min(arr[i], b[i + ]);
for (int i = ; i < n - ; ++i) {
if (f[i] <= b[i + ]) ++res;
}
return res;
}
};
我们可以优化一下空间复杂度,因为我们可以在遍历的过程中维护一个当前最大值curMax,所以就不用一个专门的forward数组了,但是backward数组还是要的,参见代码如下:
解法三:
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int res = , n = arr.size(), curMax = INT_MIN;
vector<int> b = arr;
for (int i = n - ; i >= ; --i) b[i] = min(arr[i], b[i + ]);
for (int i = ; i < n - ; ++i) {
curMax = max(curMax, arr[i]);
if (curMax <= b[i + ]) ++res;
}
return res;
}
};
下面这种使用单调栈Monotonous Stack的解法的题也十分的巧妙,我们维护一个单调递增的栈,遇到大于等于栈顶元素的数字就压入栈,当遇到小于栈顶元素的数字后,处理的方法很是巧妙啊:首先取出栈顶元素,这个是当前最大值,因为我们维护的就是单调递增栈啊,然后我们再进行循环,如果栈不为空,且新的栈顶元素大于当前数字,则移除栈顶元素。这步简直绝了,这里我们单调栈的元素个数实际上是遍历到当前数字之前可以拆分成的块儿的个数,我们遇到一个大于栈顶的元素,就将其压入栈,suppose其是一个新块儿的开头,但是一旦后面遇到小的数字了,我们就要反过来检查前面的数字,有可能我们之前认为的可以拆分成块儿的地方,现在就不能拆了,举个栗子来说吧:
比如数组为 [1 0 3 3 2],我们先把第一个数字1压入栈,此时栈为:
stack:1
然后遍历到第二个数字0,发现小于栈顶元素,将栈顶元素1取出存入curMax,此时栈为空了,不做任何操作,将curMax压回栈,此时栈为:
stack:1
然后遍历到第三个数字3,大于栈顶元素,压入栈,此时栈为:
stack:1,3
然后遍历到第四个数字3,等于栈顶元素,压入栈,此时栈为:
stack:1,3,3
然后遍历到第五个数字2,小于栈顶元素,将栈顶元素3取出存入curMax,此时新的栈顶元素3,大于当前数字2,移除此栈顶元素3,然后新的栈顶元素1,小于当前数字2,循环结束,将curMax压回栈,此时栈为:
stack:1,3
所以最终能拆为两个块儿,即stack中数字的个数,参见代码如下:
解法四:
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
stack<int> st;
for (int i = ; i < arr.size(); ++i) {
if (st.empty() || st.top() <= arr[i]) {
st.push(arr[i]);
} else {
int curMax = st.top(); st.pop();
while (!st.empty() && st.top() > arr[i]) st.pop();
st.push(curMax);
}
}
return st.size();
}
};
类似题目:
参考资料:
https://leetcode.com/problems/max-chunks-to-make-sorted-ii/
https://leetcode.com/problems/max-chunks-to-make-sorted-ii/discuss/113464/C++-9-lines-15ms
https://leetcode.com/problems/max-chunks-to-make-sorted-ii/discuss/120336/Stack-Solution-in-Java
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Max Chunks To Make Sorted II 可排序的最大块数之二的更多相关文章
- [LeetCode] 768. Max Chunks To Make Sorted II 可排序的最大块数 II
This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...
- [leetcode]Weekly Contest 68 (767. Reorganize String&&769. Max Chunks To Make Sorted&&768. Max Chunks To Make Sorted II)
766. Toeplitz Matrix 第一题不说,贼麻瓜,好久没以比赛的状态写题,这个题浪费了快40分钟,我真是...... 767. Reorganize String 就是给你一个字符串,能不 ...
- [LeetCode] Max Chunks To Make Sorted 可排序的最大块数
Given an array arr that is a permutation of [0, 1, ..., arr.length - 1], we split the array into som ...
- 【LeetCode】768. Max Chunks To Make Sorted II 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/max-chun ...
- LeetCode - 768. Max Chunks To Make Sorted II
This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...
- [Swift]LeetCode768. 最多能完成排序的块 II | Max Chunks To Make Sorted II
This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...
- 768. Max Chunks To Make Sorted II
This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...
- Max Chunks To Make Sorted II LT768
This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...
- [LeetCode] 769. Max Chunks To Make Sorted 可排序的最大块数
Given an array arr that is a permutation of [0, 1, ..., arr.length - 1], we split the array into som ...
随机推荐
- 计时器setInterval()、setTimeout()
计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码. 语法: setInterval(代码,交互时间); 参数说明: 1. 代码:要调用的函数或要执行的代码串. 2. 交互 ...
- [poj2367]Genealogical tree_拓扑排序
Genealogical tree poj-2367 题目大意:给你一个n个点关系网,求任意一个满足这个关系网的序列,使得前者是后者的上级. 注释:1<=n<=100. 想法:刚刚学习to ...
- 一个C&C++程序的生命历程
翻了好多博客,内容星星点点,没找到我想要的,现在吸取大神精华,加上本人拙见,总结如下: 一个C或C++程序从你开始编写,到结束,整个过程,都做了些什么,请看下文: 先看大体的过程:看图: 我在这里主要 ...
- Python习题(第一课)
想了想其他的太简单了,还是不放了,剩三题吧. 一.完美立方 编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3 + c^3 + d^3,其中 ...
- video与audio的使用
HTML5 DOM 为 <audio> 和 <video> 元素提供了方法.属性和事件. 这些方法.属性和事件允许您使用 JavaScript 来操作 <audio> ...
- 《javascript设计模式与开发实践》阅读笔记(13)—— 职责链模式
职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 书里的订单的例子 假设我们负责一个售卖手机 ...
- python之路--day15--常用模块之logging模块
常用模块 1 logging模块 日志级别:Noset (不设置) Debug---(调试信息)----也可用10表示 Info--(消息信息)----也可用20表示 Warning---(警告信息) ...
- Linux的rsync 配置,用于服务器之间远程传大量的数据
[教程主题]:rsync [课程录制]: 创E [主要内容] [1] rsync介绍 Rsync(Remote Synchronize) 是一个远程资料同步工具,可通过LAN/WAN快速同步多台主机, ...
- 容器化的 DevOps 工作流
对于 devops 来说,容器技术绝对是我们笑傲江湖的法宝.本文通过一个小 demo 来介绍如何使用容器技术来改进我们的 devops 工作流. devops 的日常工作中难免会有一些繁琐的重复性劳动 ...
- eclipse+Maven插件报错:-Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match.
问题描述: eclipse indigo+maven3.3.3+jdk1.70 maven插件执行报错:-Dmaven.multiModuleProjectDirectory system prope ...