作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址: https://leetcode.com/problems/max-chunks-to-make-sorted-ii/description/

题目描述:

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:

  1. arr will have length in range [1, 2000].
  2. arr[i] will be an integer in range [0, 10**8].

题目大意

把可能含有重复数字的数组分为尽可能多的块,使得每个块分别进行排序后拼接在一起,能得到整体有序的数值。

解题方法

这个题是769. Max Chunks To Make Sorted的变形,769题的数字范围是0~N-1不重复的数字。可是这个题改成了可能包含有重复的数字。

Grandyang大神的可排序的最大块数之二一文已经总结的非常好了,先给他赞一个。

方法一:

第一种方法就是观察分块的结果和原始数组排序的结果,发现每个块中的元素和与对应的排序切片的元素和是相等,所以根据这个可以解决。

 2  1    4  3    4

(1  2)  (3  4)  (4)

 1  2    3  4    4

可能会想到为什么和相等就能判断一定是在同一个块中?比如上面的4,3和是7,会不会出现5,2和也是7导致判断错误呢?看一个例子就知道了,数字不同会排序到不同的位置的,所以不用多虑。

 2  1     5   2   4

(1  2)   (2   4   5)

 1  2     2   4   5

代码中,我把划分出每个块之后的sum1,sum2复原成0,对于Python没有必要,但是对于c++和java要注意是否会超过int范围。

时间复杂度是O(N*log(N)),空间复杂度是O(1)。其中N是所有数组的长度。

class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
asort = sorted(arr)
res = 0
sum1 = 0
sum2 = 0
for i, a in enumerate(arr):
sum1 += a
sum2 += asort[i]
if sum1 == sum2:
res += 1
sum1 = 0
sum2 = 0
return res

方法二:

考虑一下是什么导致分块的位置呢?应该是小的数字跑到了后面,这样就不得不把它和前面的数字划分到一个组,这样排序之后才会在前面。所以使用两个数组,f数组保存每个位置之前出现的最大值,b数组保存每个数字之后出现的最小值,然后对每个位置进行一个判断:如果这个数字之前的最大值 <= 这个数字之后的最小值,那么这个数字可以成为一个新的分块。这个意思是我们后面的数字都比较大,你前面就放心分块吧!

举个栗子:

nums    2   1   3   4   4
f 2 2 3 4 4
b 1 1 3 4 4
结果 (1, 2) (3) (4) (4)

代码如下:

时间复杂度是O(N),空间复杂度是O(1)。其中N是所有数组的长度。

class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
n = len(arr)
res = 1
f, b = [0] * n, [0] * n
f[0] = arr[0]
b[-1] = arr[-1]
for i in range(1, n):
f[i] = max(arr[i], f[i - 1])
for i in range(n - 2, -1, -1):
b[i] = min(arr[i], b[i + 1])
for i in range(n - 1):
if f[i] <= b[i + 1]:
res += 1
return res

方法三:

使用单调栈Monotonous Stack。单调栈我之前看到过设计题,但是这是第一次使用。

单调栈从底至顶是单调递增的,其保存的是到目前为止的遇到的最大值。当一个新元素到达的时候,如果比栈顶大,直接进栈;如果比栈顶小,那么保存一下栈顶curMax,再对栈进行出栈操作直至栈顶元素小于当前元素,最后再把curMax入栈。这样遍历一遍所有的数字之后,得到的栈中的元素个数就是我们要求的块的个数。

这个道理和方法二基本一样的,导致块数变少的原因是来自后面出现了一个较小的元素。这个较小元素的存在,导致了我们必须把它划分到前面去,所以就一路打通到前面一个比它小的元素,这些被打通的元素属于同一个块。最后把curMax进栈,curMax的含义是我们前面一个块的最大值,也就是每个块排序后的最后一个元素。所以最后栈里多少个元素就是我们有多少个块,栈里的每个元素是每个块的结尾元素。用Grandyang的栗子如下:

比如数组为 [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中数字的个数。

时间复杂度是O(N),空间复杂度是O(1)。其中N是所有数组的长度。

class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
n = len(arr)
stack = list()
stack.append(arr[0])
curMax = arr[0]
for i in range(1, n):
if arr[i] >= stack[-1]:
stack.append(arr[i])
else:
curMax = stack[-1]
while stack and arr[i] < stack[-1]:
stack.pop()
stack.append(curMax)
return len(stack)

参考资料:

http://www.cnblogs.com/grandyang/p/8850299.html

日期

2018 年 10 月 3 日 —— 玩游戏导致没睡好,脑子是浆糊。

【LeetCode】768. Max Chunks To Make Sorted II 解题报告(Python)的更多相关文章

  1. [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 ...

  2. 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 ...

  3. [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 就是给你一个字符串,能不 ...

  4. 768. Max Chunks To Make Sorted II

    This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...

  5. 【LeetCode】26. Remove Duplicates from Sorted Array 解题报告(Python&C++&Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 日期 [LeetCode] https:// ...

  6. [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 ...

  7. 【LeetCode】95. Unique Binary Search Trees II 解题报告(Python)

    [LeetCode]95. Unique Binary Search Trees II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzh ...

  8. [LeetCode] Max Chunks To Make Sorted II 可排序的最大块数之二

    This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...

  9. [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 ...

随机推荐

  1. dlang 泛型

    1 import std.stdio, std.string; 2 3 void main() 4 { 5 bool find(T)(T[] all, T sub) 6 { 7 foreach(eac ...

  2. 学习Java的第三天

    一.今日收获 1.今天家里有白事,忙了一整天,也没有看更多的资料 二.今日问题 无 三.明日目标 补全今天耽误的功课,继续学习java!

  3. 超好玩:使用 Erda 构建部署应用是什么体验?

    作者|郑成 来源|尔达 Erda 公众号 导读:最近在 Erda 上体验了一下构建并部署一个应用,深感其 DevOps 平台的强大与敏捷,不过为了大家能够快速上手,我尽量简化应用程序,用一个简单的返回 ...

  4. Hive(十一)【压缩、存储】

    目录 一.Hadoop的压缩配置 1.MR支持的压缩编码 2.压缩参数配置 3.开启Mapper输出阶段压缩 4.开启Reduceer输出阶段 二.文件存储 1.列式存储和行式存储 2.TextFil ...

  5. 安全相关,CSRF

    先说下CSRF的定义 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF ...

  6. deque、queue和stack深度探索(下)

    deque如何模拟连续空间?通过源码可以看到这个模型就是通过迭代器来完成. 迭代器通过重载操作符+,-,++,--,*和->来实现deque连续的假象,如上图中的 finish-start ,它 ...

  7. springboot-使用AOP日志拦截实现

    一 前言 借助spring的AOP功能,我们可以将AOP应用至全局异常处理,全局请求拦截等,本篇文章的核心功能就是使用AOP实现日志记录,比如哪些用户进行了哪些操作,对于一个成功的项目这是必须记录的, ...

  8. Linux基础命令---ftp

    ftp ftp指令可以用来登录远程ftp服务器. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora.   1.语法       ftp [ ...

  9. 5.Vue.js-模板语法

    Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据. Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统 ...

  10. Mysql的基操

    创建一个数据库   (myschool是数据库名) create database myschool; 删除数据库 drop database myschool 创建一个表:(Student是 表名) ...