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

一、题目

这个问题和“最多能完成排序的块”相似,但给定数组中的元素可以重复,输入数组最大长度为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)/ ~ 「干货分享,每天更新」

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容