一、题目

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

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

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

二、示例

2.1> 示例 1:

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

2.2> 示例 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]之间。

三、解题思路

3.1> 堆栈 + top指针

根据题意,我们要计算出最多的分组块数。那么约束条件就是,无论分成多少组,只要我们满足,在每个子组内对元素进行升序排序之后,组成的总的数组与将整体数组按照升序排列的结果是一样的就可以了。题目比较绕嘴,我们可以举个例子,比如:原有的数组为:arr = [2,1,4,3,7,8],那么如果我们按照升序排列的话,最终结果就是:arr=[1,2,3,4,7,8]。那么,如果我们先执行分组,再执行每个分组内部元素的排序,最终结果也要保证是arr=[1,2,3,4,7,8]。比如,我们将原数组arr = [2,1,4,3,7,8]分成两部分,即:[2,1,4,3][7,8],那么分别对这两个数组内部的元素进行升序排序,结果为:[1,2,3,4][7,8],那么将这两个数组拼装在一起,就是[1,2,3,4,7,8],那么这种分组方式,就满足了题目中的条件了。具体操作,如下图所示:

不过,需要注意的是,题目中要求获得的是最多的分组块数,所以,我们最终的分组情况应该是[2,1][4,3][7][8]这四组,才满足最多分组块数并且最终排序结果为[1,2,3,4,7,8]。具体操作,如下图所示:

我们现在了解了题目的含义。那么,如何去计算分组呢?其实在上面的两个分组的例子中,我们也能找到一些规律。比如,以上面的例子为例,分为了四组,分别为[2,1][4,3][7][8]这四组。那么我们可以发现,当某一个组内最大的那个值,它大于组内的任意一个元素同时它小于任意一个组外的元素,那么,就可以满足分组排序后结果依然是整体升序了。按照题目中升序的条件,我们可以采用堆栈的方式进行数据的存储,但是,我们没有必要存储所有的元素,因为只要知道最多分多少组就可以了,而并不需要知道每个分组的详情。所以,我们将满足条件的组内最大值存入到堆栈中即可。

这里面具体操作有如下几个步骤:

  • 首先:如果堆栈为空,或者遍历到当前数组元素大于等于栈顶元素(top)的话,就将该元素(arr[index])执行入栈操作。
  • 其次:如果arr[index]小于栈顶元素,则去对比除栈顶元素之外的元素(可以先pop()掉栈顶元素进行缓存,然后最后再push到堆栈中),如果对比堆栈中的元素大于arr[index],则将堆栈中的该元素执行出栈操作(执行pop()操作);否则,结束对比。
  • 最后:将堆栈中存在元素进行总和统计,返回的数量就是可以拆分最大分组数量。

了解到了具体的操作步骤之后,我们再通过一个例子,来看一下具体的操作过程是怎样的。 我们以arr = [4,2,6,1,8,7,9,10]为例。从头开始遍历数组中的每个元素。首先,因为堆栈中是空的,所以,我们将index[0]=4这个元素插入到堆栈中;遍历第二个元素index[1]=2,由于栈顶top只有一个元素,并且它小于top指向的元素,所以,没有元素出栈和入栈;遍历第三个元素index[2]=6,由于它大于top元素,所以,将6指向入栈操作,此时堆栈中存在两个元素,分别为:4和6。具体操作,如下图所示:

遍历第四个元素index[3]=1,由于它小于栈顶top元素,所以继续对比非top的元素,因为index[3] < 4,所以4被踢出堆栈,执行pop()方法。由于此时4这个元素已经是在栈底了,没有可以对比的其他元素了,所以结束对比操作;继续遍历第五个元素index[4]=8,由于大于top栈顶元素,所以执行入栈操作,此时堆栈中保存的元素为:6和8;继续遍历第六个元素index[5]=7,由于它小于栈顶元素top,所以对比非top的元素,由于index[5] > 6,所以元素6不用出栈,依然保存在堆栈中,并结束对比操作。具体操作,如下图所示:

遍历第七个元素index[6]=9,由于它大于top栈顶元素8,所以执行入栈操作;遍历第八个元素index[7]=10,由于它大于top栈顶元素9,所以执行入栈操作;遍历所有数组结束之后,堆栈中保存的元素为:6、8、9、10,总数是4,所以最终可以分组的最大数量为4。

以上就是解题思路和具体例子的分步骤操作演示。代码实现,请参照: 4.1> 堆栈 + top指针

四、代码实现

4.1> 堆栈 + top指针

class Solution {public int maxChunksToSorted(int[] arr) {Deque<Integer> stack = new ArrayDeque();stack.push(arr[0]);for (int i = 1; i < arr.length; i++) {int top = stack.peek();if (top <= arr[i]) {stack.push(arr[i]);} else {while(!stack.isEmpty()) {int stackElements = stack.peek();if (stackElements > arr[i]) {stack.pop();} else {break;}}stack.push(top);}}return stack.size();}
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

图解LeetCode——768. 最多能完成排序的块 II(难度:困难)相关推荐

  1. Leetcode 768. 最多能完成排序的块 II C++

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

  2. Java实现 LeetCode 768 最多能完成排序的块 II(左右便利)

    768. 最多能完成排序的块 II 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含 ...

  3. 768. 最多能完成排序的块 II 贪心

    768. 最多能完成排序的块 II 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含 ...

  4. 768. 最多能完成排序的块 II

    这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含重复元素的整数数组,我们将这个数组分 ...

  5. 常规贪心构造题 最多能完成排序的块 II

    这是 LeetCode 上的  最多能完成排序的块 II ,难度为 困难. Tag : 「贪心」 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度 ...

  6. LeetCode 最多能完成排序的块II

    这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含重复元素的整数数组,我们将这个数组分 ...

  7. Java实现 LeetCode 769 最多能完成排序的块(单向遍历)

    769. 最多能完成排序的块 数组arr是[0, 1, -, arr.length - 1]的一种排列,我们将这个数组分割成几个"块",并将这些块分别进行排序.之后再连接起来,使得 ...

  8. LeetCode 769. 最多能完成排序的块

    1. 题目 数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个"块",并将这些块分别进行排序. 之后再连接起来,使得连接的结果和 ...

  9. Leetcode 769 最多能完成排序的块

    数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个"块",并将这些块分别进行排序.之后再连接起来,使得连接的结果和按升序排序后的 ...

最新文章

  1. 边缘检测、霍夫变换、重映射、仿射变换、直方图均衡化
  2. 宇宙中至少有两种方式能灭绝人类,第一种仅需两秒
  3. 毫米波雷达_毫米波雷达基础知识
  4. vue中axios请求的封装
  5. java list详解_Java 中 list 用法案例详解
  6. JAVA标准输出错误输出,从tsls输出中提取标准错误
  7. 有关CentOS的常见问题
  8. php过滤非法字符函数,非法字符过滤_PHP教程
  9. div标签清除float浮动样式方法
  10. IDEA初始jsp模板和修改jsp模板
  11. 关于 np.arccos/arcsin 计算之前需要必须要 np.clip 的那件小事儿
  12. MAC 清除 DNS 缓存
  13. 天池竞赛 | 中医药领域的问题生成冠军方案
  14. (难度:35%)untrusted游戏通关攻略
  15. Gitlab内存占用过高的解决方法
  16. 机器学习HMM模型算法实例
  17. 她是好莱坞巨星,Wi-Fi之母!没有她,可能我们刷不了手机!
  18. 辩证法的本质及应用实例:微积分新诠释
  19. 超融合市场的战争远未结束,谁将最终胜出?
  20. Pro Android学习笔记(四八) ActionBar(1) Home图标区

热门文章

  1. (八)QRJDC正式版/QQ扫码登录直达青龙/Docker上的部署教程/很干很干/没水喝【2020年5月1日】
  2. 国内AdSense/Youtube如何回款?AdSense/Youtube无限额结汇
  3. 1178_hardware_basic_什么是高阻态
  4. (算法)海盗分赃_2
  5. 数据库是什么?数据库的概念
  6. vue组件测试-Vue Test Utils 应用入门
  7. JQuery-回到顶部
  8. 【二】gym初次入门一学就会---代码详细解析简明教程----平衡杆案例
  9. 量化交易摸索-角度计算
  10. 数据为王,聚数学院引领大数据新时代