Open azl397985856 opened 2 years ago
单调栈
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList<Integer> stack = new LinkedList<Integer>();
for(int num : arr) {
if(!stack.isEmpty() && num < stack.getLast()) {
int head = stack.removeLast();
while(!stack.isEmpty() && num < stack.getLast()) stack.removeLast();
stack.addLast(head);
}
else stack.addLast(num);
}
return stack.size();
}
}
C++ Code:
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
/// increase stack.
vector<int> stack; // increase stack.
int imax = arr[0];
for(int i=0; i< arr.size(); i++)
{
imax = max(imax, arr[i]) ;
while(stack.size() && (arr[i]<stack.back()) )
{
stack.pop_back();
}
stack.push_back(imax);
}
return stack.size();
}
};
这题研究了半天也不会, 实在是没辙了, 最后结合单调栈的模版还有官方解答匹配出来的代码
基本就是结合单调栈的递增的概念,pop出栈中小的元素,保留最大的元素,返回的是栈的长度
def maxChunksToSorted(self, arr: List[int]) -> int:
# Initialize a stack
stack = []
# loop through all the element in arr
for element in arr:
# find the largest value in the stack and set to -1
# because stack is increasing
if stack and stack[-1] > element:
# set the largest value in stack
larger = stack[-1]
# keep the stack increasing (递增)
while stack and stack[-1] > element: stack.pop()
stack.append(larger)
else:
stack.append(element)
return len(stack)
单调递增栈,遍历数组,保存每个排序块的最大数字:
否则,当前数字要合并到栈顶数字的块里,栈内数字依次出栈,直到栈顶<=当前数字。再把原来的栈顶入栈。 最后返回栈长度。
class Solution {
public int maxChunksToSorted(int[] arr) {
Deque<Integer> stack = new LinkedList<>();
for (int num : arr) {
if (stack.isEmpty() || stack.peek() <= num) {
stack.push(num);
} else {
int top = stack.pop();
while (!stack.isEmpty() && stack.peek() > num) {
stack.pop();
}
stack.push(top);
}
}
return stack.size();
}
}
TC: O(n) SC: O(n)
借鉴题解 单调栈:要想保证每一个块拼接后单调递增,就要保证每一个块的最大值是单调递增的,这时候就可以构建一个单调栈。 具体做法: 1.遍历数组arr中的每一个num 2.当stack为空或者num>=栈顶值时:入栈(相当于添加了新的元素块) 3.当栈 stack 不为空且数字 num<栈顶值 时: (1)保存栈顶值head *(2)当栈 stack 不为空且数字 num<栈顶值 时:循环出栈(此步是关键,因为num>=栈顶值时才能保证有序,所以要将前面所有的大于num的块儿合成一个) (3)将head入栈(当前块的最大值) 4.遍历结束后,stack的长度就是块的个数(很好理解,想一下就明白了)
func maxChunksToSorted(arr []int) int {
if len(arr) == 0{
return 0
}
stack := []int{}
head := -1
for i:=0;i<len(arr);i++{
if len(stack) == 0 || arr[i] >= head{
stack = append(stack,arr[i])
head = arr[i]
}else if arr[i]<head{
for len(stack)!= 0 &&stack[len(stack)-1]>arr[i]{
stack = stack[:len(stack)-1]
}
stack = append(stack,head)
}
}
return len(stack)
}
时间:O(n) 空间:O(n)
用栈存下可以划块的最大值,如果下个值比栈顶的值要大,则直接入栈。如果小于栈顶的值,说明当前的值不能单独划块,需要和栈顶的值放到同一个块中。同时也需要继续遍历栈中的元素,因为只有前面分的块最大值要小于当前值,才能保证分块正确。不然该块应该也被划分到栈顶的块中
JavaScript Code:
/**
* @param {number[]} arr
* @return {number}
*/
var maxChunksToSorted = function(arr) {
let stack = []
for (let i = 0; i < arr.length; i++) {
let cur = arr[i]
if (stack.length && stack[stack.length - 1] > cur) {
let top = stack[stack.length - 1]
while(stack.length && stack[stack.length - 1] > cur) {
stack.pop()
}
stack.push(top)
} else {
stack.push(cur)
}
}
return stack.length
};
复杂度分析
令 n 为数组长度。
class Solution {
public int maxChunksToSorted(int[] arr) {
Stack<Integer> stack = new Stack<>();
for(int i = 0; i < arr.length; i++) {
if(stack.isEmpty() || arr[i] >= stack.peek()) {
stack.push(arr[i]);
} else {
int head = stack.pop();
while(!stack.isEmpty() && arr[i] < stack.peek() ) {
stack.pop();
}
stack.push(head);
}
}
return stack.size();
}
}
复杂度分析
func maxChunksToSorted(arr []int) int {
stack := []int{}
for _,x := range arr{
if len(stack)>0 && x < stack[len(stack)-1]{
temp := stack[len(stack)-1]
for len(stack)>0 && x < stack[len(stack)-1]{
stack = stack[:len(stack)-1]
}
stack = append(stack,temp)
}else{
stack = append(stack,x)
}
}
return len(stack)
}
复杂度为n
class Solution { public int maxChunksToSorted(int[] arr) { Map<Integer, Integer> count = new HashMap(); int ans = 0, nonzero = 0;
int[] expect = arr.clone();
Arrays.sort(expect);
for (int i = 0; i < arr.length; ++i) {
int x = arr[i], y = expect[i];
count.put(x, count.getOrDefault(x, 0) + 1);
if (count.get(x) == 0) nonzero--;
if (count.get(x) == 1) nonzero++;
count.put(y, count.getOrDefault(y, 0) - 1);
if (count.get(y) == -1) nonzero++;
if (count.get(y) == 0) nonzero--;
if (nonzero == 0) ans++;
}
return ans;
}
} 时间复杂度: O(N \log N)O(NlogN) 空间复杂度: O(N)O(N)
用一个单调不减辅助栈存储每个排序块的最大值。具体来说:
遍历数组获得当前元素num
,
栈空或num
大于等于栈顶元素:说明num
不会影响当前排序块,直接进栈,把当前num
当作一个只有一个元素的排序块
栈不空且num
小于栈顶元素:说明num
会影响当前排序块,需要把num
并入当前排序块。用中间变量head
存储出栈的元素,此时,head
仍是当前排序块的最大值,若num
仍小于栈顶元素(非head
,已经出栈了),则循环出栈,一直到num
大于等于栈顶元素为止,再把head
(当前排序块的最大值)入栈(num
元素并入了当前排序块),此时的栈是单调不减栈,表示现今每一个排序块的最大值。
循环往复,直至遍历结束。
遍历结束后,该单调不增辅助栈存储的是所有排序块的最大值,也即栈的长度就是排序块的最大数量。
import java.util.LinkedList;
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList<Integer> list = new LinkedList<>();
for (int num : arr) {
if (list.isEmpty() || num >= list.getLast()) {
list.addLast(num);
} else {
int head = list.removeLast();
while (!list.isEmpty() && num < list.getLast()) list.removeLast();
// 上面的代码用了短路与,如果判断条件num < list.getLast()在前,当栈为空时会出现判断错误,所以一定需要先确保栈不空再进行栈顶元素的判断
list.addLast(head);
}
}
return list.size();
}
}
对栈顶元素进行判断时,一定要先对栈空与否进行判断。
设此块中最大的为head,如果后面的数都大于等于head,那么就是排序快;如果后面的数小于head,应该将其并入块。这种单调不减的性质,考虑用单调栈来实现。
遍历数组arr,如果当前的数大于等于栈顶的数,则入栈;如果小于栈顶的数,则应将其并入块,同时将栈顶元素弹出记为head,如果后续的栈顶元素依旧大于当前数,说明这些栈顶元素应该并入块,一直弹出,再将head压入。head用于表示排序快的最大数。
var maxChunksToSorted = function(arr) {
let stack = [];
let head = 0;
for(let num of arr){
if(stack.length > 0 && num < stack[stack.length - 1]){
head = stack.pop();
while(stack.length > 0 && num < stack[stack.length - 1]){
stack.pop();
}
stack.push(head);
} else{
stack.push(num);
}
}
return stack.length;
};
复杂度分析
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
stack = []
for x in arr:
if not stack or stack[-1] <= x:
stack.append(x)
elif stack[-1] > x:
tmp = stack[-1]
while stack and stack[-1] > x:
stack.pop()
stack.append(tmp)
return len(stack)
var maxChunksToSorted = function(arr) {
let stack = []
for (let index = 0; index < arr.length; index++) {
if (stack.length && arr[index] < stack[stack.length - 1]) {
const cur = stack[stack.length - 1]
while (stack.length && arr[index] < stack[stack.length - 1]) {
stack.pop()
}
stack.push(cur)
} else {
stack.push(arr[index])
}
}
return stack.length
};
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
stack = []
for i in range(len(arr)):
if stack and stack[-1] > arr[i]:
cur_ = stack.pop()
while stack and stack[-1] > arr[i]:
stack.pop()
stack.append(cur_)
else:
stack.append(arr[i])
return len(stack)
JavaScript Code:
/**
* @param {number[]} arr
* @return {number}
*/
var maxChunksToSorted = function(arr) {
let stack = [];
for(let i=0;i<arr.length;i++){
if(stack.length>0&&stack[stack.length-1]>arr[i]){
const cur = stack[stack.length-1]
while(stack&&stack[stack.length-1]>arr[i]) stack.pop()
stack.push(cur)
}else{
stack.push(arr[i])
}
}
return stack.length
};
复杂度分析
令 n 为数组长度。
单调栈
class Solution:
def findblock(self, L: list) -> int:
stack = []
for l in L:
if stack and l<stack[-1]:
s = stack[-1]
while stack and l < stack[-1]:
stack.pop()
stack.append(s)
else:
stack.append(l)
return len(stack)
复杂度分析
class Solution { public int maxChunksToSorted(int[] arr) { int n = arr.length; int[] maxOfLeft = new int[n]; int[] minOfRight = new int[n];
maxOfLeft[0] = arr[0];
for (int i = 1; i < n; i++) {
maxOfLeft[i] = Math.max(maxOfLeft[i-1], arr[i]);
}
minOfRight[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; i--) {
minOfRight[i] = Math.min(minOfRight[i + 1], arr[i]);
}
int res = 0;
for (int i = 0; i < n - 1; i++) {
if (maxOfLeft[i] <= minOfRight[i + 1]) res++;
}
return res + 1;
}
}
class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
stack = []
for a in arr:
if stack and a < stack[-1]:
cur = stack[-1]
while stack and a < stack[-1]:
stack.pop()
stack.append(cur)
else:
stack.append(a)
return len(stack)
时间复杂度:O(N)
空间复杂度:O(N)
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList<Integer> stack = new LinkedList<Integer>();
for(int num : arr){
if(!stack.isEmpty() && num < stack.getLast()) {
int head = stack.removeLast();
while(!stack.isEmpty() && num < stack.getLast()) stack.removeLast();
stack.addLast(head);
}
else stack.addLast(num);
}
return stack.size();
}
}
复杂度分析 时间复杂度:$0(N)$ 空间复杂度:$0(N)$
def maxChunksToSorted(arr): stack = [arr[0]] for num in arr[1:]:
if num >= stack[-1]: # 大于栈顶【栈中的最大值】
stack.append(num)
else: # 小于栈顶
cur_ma = stack.pop() # 记录下栈顶
while stack and num < stack[-1]: # 移除栈中大于当前值num的所有元素
stack.pop()
stack.append(cur_ma) # 栈顶复位
return len(stack)
思路
计数排序
两个数组的计数信息如果一致,那么两个数组的排序结果一致;
遍历排序后的arr_s和arr,比较当前阶段arr_s和arr的计数信息是否一致,如果一致表示可以在此处分块。
代码
class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
count = collections.defaultdict(int)
bound = 0
ans = 0
for x, y in zip(arr, sorted(arr)):
if count[x] == -1:
bound -= 1
if count[x] == 0:
bound += 1
count[x] += 1
if count[y] == 1:
bound -= 1
if count[y] == 0:
bound += 1
count[y] -= 1
if bound == 0:
ans += 1
return ans
复杂度分析
时间复杂度:O(N*logN)
空间复杂度:O(N)
找到数组左边最小值,然后依次对比,
/**
* @param {number[]} arr
* @return {number}
*/
var maxChunksToSorted = function(arr) {
const minWithIndex = new Map();
for(let i = arr.length-1; i > -1; i--){
if(i == arr.length-1){
minWithIndex.set(i, arr[i]);
}
else{
minWithIndex.set(i, Math.min(minWithIndex.get(i+1), arr[i]));
}
}
let blocks = 1, max = 0;
for(let i = 0; i < arr.length; i++){
max = arr[max]>=arr[i]? max:i;
if(arr[max] <= minWithIndex.get(i+1)){
blocks++;
}
}
return blocks;
};
时间复杂度:o(n)
class Solution { public int maxChunksToSorted(int[] arr) { int n = arr.length; int[] forward = new int[n]; int[] backward = new int[n];
forward[0] = arr[0];
for (int i = 1; i < n; i++) {
forward[i] = Math.max(forward[i-1], arr[i]);
}
backward[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; i--) {
backward[i] = Math.min(backward[i + 1], arr[i]);
}
int res = 0;
for (int i = 0; i < n - 1; i++) {
if (forward[i] <= backward[i + 1]) res++;
}
return res + 1;
}
}
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
arr_sort = arr.copy()
arr_sort.sort()
count = 0
for i in range (len(arr)):
arr_sub = arr[:(i+1)]
arr_sort_sub = arr_sort[:(i+1)]
arr_sub.sort()
arr_sort_sub.sort()
if arr_sub == arr_sort_sub:
count += 1
return count
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
stack = []
for a in arr:
if stack and stack[-1] > a:
cur = stack[-1]
while stack and stack[-1] > a:
stack.pop()
stack.append(cur)
else:
stack.append(a)
return len(stack)
class Solution {
public int maxChunksToSorted(int[] arr) {
int[] sortedArray = arr.clone();
Arrays.sort(sortedArray);
long arrSum = 0;
long sortedSum = 0;
int chunkCount = 0;
for (int i = 0; i < arr.length; i++) {
arrSum += arr[i];
sortedSum += sortedArray[i];
if(arrSum == sortedSum) chunkCount++;
}
return chunkCount;
}
}
时间复杂度:O(NlogN),N 为数组长度,数组排序时间认为是 NlogN,滑动窗口遍历数组时间为 N。;
空间复杂度:O(N);
我们知道数组 arr 在排序之后一定跟整个数组排序后相应的地方完全相同,即 expect = sorted(arr)。如果前 k 个元素的个数减去排序后前 k 个元素的个数都为 0 的话,那这前 k 个元素是可以成为一个合法的分块的。对于整个数组可以重复这一过程。
用变量 nonzero 来计数目前差值不等于 0 的字符的个数。
class Solution {
public int maxChunksToSorted(int[] arr) {
Map<Integer, Integer> count = new HashMap();
int ans = 0, nonzero = 0;
int[] expect = arr.clone();
Arrays.sort(expect);
for (int i = 0; i < arr.length; ++i) {
int x = arr[i], y = expect[i];
count.put(x, count.getOrDefault(x, 0) + 1);
if (count.get(x) == 0) nonzero--;
if (count.get(x) == 1) nonzero++;
count.put(y, count.getOrDefault(y, 0) - 1);
if (count.get(y) == -1) nonzero++;
if (count.get(y) == 0) nonzero--;
if (nonzero == 0) ans++;
}
return ans;
}
}
时间复杂度: O(NlogN),其中 N 为 arr 的长度。 空间复杂度: O(N)。
利用单调栈
class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
stack = [arr[0]]
for num in arr[1:]:
if stack[-1]<=num:
stack.append(num)
else:
curr = stack[-1] #记录栈顶
stack.pop()
while stack and stack[-1]>num:
stack.pop()
stack.append(curr) #复位
return len(stack)
空间 O(n)
时间 O(n)
var maxChunksToSorted = function (arr) { const sorted = [...arr]; sorted.sort((a, b) => a - b); let count = 0, sum1 = 0, sum2 = 0; for (let i = 0; i < arr.length; i++) { sum1 += arr[i]; sum2 += sorted[i]; if (sum1 === sum2) count++; } return count; };
思路
贪心 将整个数组 a 排序记作 b,a 的第一部分和b 的第一部分应该是一样的,a 的第二部分和b 的第二部分应该是一样的,依次类推。 从左往右遍历 a,当扫描到第一个位置 n,使得a[0,n] 和 b[0,n] 的元素是一致的,那么 [0,n] 就可以作为一个区间,依次类推。
代码 function maxChunksToSorted(arr: number[]): number { let res = 0; // 把原始数组 arr 进行排序 let b = [...arr].sort((a, b) => a - b); // 定义 map,key 是 arr 的每一个元素,值的初始值为 0 let m = new Map(); arr.forEach((x) => m.set(x, 0)); // m[arr[i]] 的值是否为零,也就是在这个区间里,arr[i] 同时在 arr 和 b 里 for (let i = 0, s = 0; i < arr.length; i++) { if (m.get(arr[i]) === 1) s -= 1; else if (m.get(arr[i]) === 0) s += 1; m.set(arr[i], m.get(arr[i]) - 1); if (m.get(b[i]) === -1) s -= 1; else if (m.get(b[i]) === 0) s += 1; m.set(b[i], m.get(b[i]) + 1); if (!s) res += 1; } return res; }
分析 时间复杂度 O(nlogn) 空间复杂度 O(n)
public int maxChunksToSorted(int[] arr) {
Stack<Integer> stack = new Stack<>();
for (int i=0; i<arr.length; i++) {
if (stack.isEmpty() || stack.peek() <= arr[i]) {
stack.add(arr[i]);
}
else if (stack.peek() > arr[i]) {
int top = stack.pop();
while (!stack.isEmpty() && stack.peek() > arr[i]) stack.pop();
stack.add(top);
}
}
return stack.size();
}
mint[i]
;maxt[i]
;class Solution(object):
def maxChunksToSorted(self, arr):
"""
:type arr: List[int]
:rtype: int
"""
res=1
maxt=[0]*len(arr)
maxt[0]=arr[0]
mint=[0]*len(arr)
mint[-1]=arr[-1]
for i in reversed(range(len(arr)-1)):
mint[i]=min(arr[i],mint[i+1])
for i in range(1,len(arr)):
maxt[i]=max(arr[i],maxt[i-1])
for i in range(len(arr)-1):
if maxt[i] <= mint[i+1]:
res=res+1
return res
JavaScript 思路: 最主要的思路是 当数组里某一项小于之前栈里面的任何一项时,pop,然后继续走
var maxChunksToSorted = function(arr) {
let stack = [arr[0]];
let max = arr[0];
for(let i = 1; i < arr.length; i++) {
if(arr[i] >= max) {
max = arr[i];
stack.push(arr[i]);
} else {
while(stack && arr[i] < stack[stack.length - 1]) {
stack.pop();
}
stack.push(max);
}
}
return stack.length;
};
将原数组排序,对比排序数组和原数组,如果两个数组的前i项和相等,说明可以作为一个块。
var maxChunksToSorted = function (arr) {
let count = 0;
let sum1 = 0; // 存arr的前i项和
let sum2 = 0;
const arrSort = [...arr].sort((a, b) => a - b);
for (let i = 0; i < arr.length; i++) {
sum1 += arr[i];
sum2 += arrSort[i];
if (sum1 === sum2) {
count++;
}
}
return count;
}
时间复杂度: O(NlogN)
空间复杂度: O(N)
https://leetcode-cn.com/problems/max-chunks-to-make-sorted-ii/
分割的临界点判断:
一直找到下一个比当前值小的元素 把分割区块考虑为融合区块,找到一个下一个比当前值小的就融合为一块,保留当前最大值到一个栈,然后将其入另外一个栈。栈里的每一个元素就是块的最大值。
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList<Integer> stack = new LinkedList<Integer>();
for (int num: arr){
if (!stack.isEmpty() && num < stack.getLast()){
int cur = stack.removeLast();
while (!stack.isEmpty() && num < stack.getLast()){
stack.removeLast();
}
stack.addLast(cur);
}else{
stack.addLast(num);
}
}
return stack.size();
}
}
思路
代码
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
stack = []
for i in arr:
if len(stack)==0:
stack.append(i)
elif i >= stack[-1]:
stack.append(i)
elif i < stack[-1]:
head = stack.pop()
while len(stack) > 0:
if i < stack[-1]:
stack.pop()
else:
break
stack.append(head)
return len(stack)
复杂度
这个确实不会了,直接看的题解
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList
JavaScript Code:
/**
* @param {number[]} arr
* @return {number}
*/
var maxChunksToSorted = function (arr) {
let stack = [];
for (var i = 0; i < arr.length; i++) {
let head;
// 合并
if (stack.length > 0 && stack[stack.length - 1] > arr[i]) {
head = stack.pop();
while (stack.length > 0 && stack[stack.length - 1] > arr[i]) {
stack.pop();
}
stack.push(head);
} else {
// 新的块
stack.push(arr[i]);
}
}
return stack.length;
};
class Solution {
public int maxChunksToSorted(int[] arr) {
Stack<Integer> stack = new Stack<>();
for (int num : arr) {
if (!stack.isEmpty() && num < stack.peek()) {
int current = stack.pop();
while(!stack.isEmpty() && num < stack.peek()) {
stack.pop();
}
stack.push(current);
} else {
stack.push(num);
}
}
return stack.size();
}
}
单调栈
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
stack<int> stack;
for(int i =0;i<arr.size();i++){
if(!stack.empty()&&stack.top()>arr[i]){
int cur = stack.top();
while(!stack.empty()&&stack.top()>arr[i]){
stack.pop();
}
stack.push(cur);
}else{
stack.push(arr[i]);
}
}
return stack.size();
}
};
时间复杂度:O(n)
空间复杂度:O(n)
class Solution(object): def maxChunksToSorted(self, arr): """ :type arr: List[int] :rtype: int """ maximum, res = 0, 1 for i in range(len(arr)): maximum = max(arr[i], maximum) if i == len(arr) - 1: break elif min(arr[i+1:]) >= maximum: res += 1 return res
根据题意可以推出:分块意味着左边块的最大值一定≤右边的最小值,顺着这个思路,只要找到左边最大值≤右边最小值的时候,就是一个块的分界线
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int sz = arr.size();
vector<int> lptr(sz, INT_MIN);
vector<int> rptr(sz, INT_MAX);
lptr[0] = arr[0];
rptr[sz - 1] = arr[sz - 1];
for (int i = 1; i < sz; ++i) {
lptr[i] = max(lptr[i - 1], arr[i]);
rptr[sz - 1 - i] = min(rptr[sz - i], arr[sz - 1 - i]);
}
int res = 1;
for (int i = 0; i < sz - 1; ++i) {
res += lptr[i] <= rptr[i + 1];
}
return res;
}
};
复杂度分析
前块max <= 后块min
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
stack<int>maxStk;
maxStk.push(arr[0]);
for(int i=1;i<arr.size();i++){
if(arr[i]<maxStk.top()){
int maxNum=maxStk.top();
while(!maxStk.empty()&&maxStk.top()>arr[i])maxStk.pop();
maxStk.push(maxNum);
}
else maxStk.push(arr[i]);
}
return maxStk.size();
}
};
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
stack = []
for num in arr:
largest = num
while stack and stack[-1] > num:
largest = max(largest, stack.pop())
stack.append(largest)
return len(stack)
Time Complexity: O(n), Space Complexity: O(n)
class Solution {
public int maxChunksToSorted(int[] arr) {
Map<Integer, Integer> count = new HashMap();
int ans = 0, nonzero = 0;
int[] expect = arr.clone();
Arrays.sort(expect);
for (int i = 0; i < arr.length; ++i) {
int x = arr[i], y = expect[i];
count.put(x, count.getOrDefault(x, 0) + 1);
if (count.get(x) == 0) nonzero--;
if (count.get(x) == 1) nonzero++;
count.put(y, count.getOrDefault(y, 0) - 1);
if (count.get(y) == -1) nonzero++;
if (count.get(y) == 0) nonzero--;
if (nonzero == 0) ans++;
}
return ans;
}
}
时间复杂度:O(nlog(n))
空间复杂度:O(n)
// 12-17 求和-》计数
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
vector<int> res = arr;
sort(res.begin(),res.end());
int ans = 0;
long sum1 = 0, sum2 = 0;
for (int i = 0; i < arr.size(); ++i) {
sum1 += res[i];
sum2 += arr[i];
if (sum1 == sum2) ans++;
}
return ans;
}
};
这道题属实是不太会。。。
def maxChunksTOSorted(self, arr: List[int]) -> int:
stack = []
for num in arr:
if stack and num < stack[-1]:
head = stack.pop()
while stack and num < stack[-1]:
stack.pop()
stack.append(head)
else:
stack.append(num)
return len(stack)
想了很久没有思路,群里大神说的滑动窗口之后明白了,困难的还是有难度啊
public int maxChunksToSorted(int[] arr) {
int[] sortedArray = arr.clone();
Arrays.sort(sortedArray);
long arrSum = 0;
long sortedSum = 0;
int chunkCount = 0;
for (int i = 0; i < arr.length; i++) {
arrSum += arr[i];
sortedSum += sortedArray[i];
if(arrSum == sortedSum) chunkCount++;
}
return chunkCount;
}
复杂度分析 -时间复杂度:O(N) -空间复杂度:O(N)
将数组与排序之后的标准数组做对比,如果当前数组遍历到的位置数字出现次数与标准数组一致,我们就可以将其看作一个块,将统计 map 都清空,继续统计
class Solution {
public int maxChunksToSorted(int[] arr) {
// [1,1,0,0,1]
// [0,0,1,1,1]
int[] standard = arr.clone();
Arrays.sort(standard);
Map<Integer, Integer> mapStandard = new HashMap<>();
Map<Integer, Integer> mapChunks = new HashMap<>();
int res = 0;
for (int i = 0; i < arr.length; i++) {
mapChunks.put(arr[i], mapChunks.getOrDefault(arr[i], 0) + 1);
mapStandard.put(standard[i], mapStandard.getOrDefault(standard[i], 0) + 1);
if (mapStandard.equals(mapChunks)) {
mapChunks.clear();
mapStandard.clear();
res++;
}
}
return res;
}
}
From : https://github.com/dahaiyidi/awsome-leetcode
难度困难109
*这个问题和“最多能完成排序的块”相似,但给定数组中的元素可以重复,输入数组最大长度为2000
,其中的元素最大为10**8
。*
arr
是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。
我们最多能将数组分成多少块?
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
st = []
for num in arr:
if st and st[-1] > num:
head = st.pop()
j = len(st) - 1
while j >= 0 and st[j] > num:
st.pop()
j -= 1
st.append(head)
else:
st.append(num)
return len(st)
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
stack<int> st;
for(auto num: arr){
if(!st.empty() && st.top() > num){
int head = st.top(); // 存储最后一个区域的最大值
st.pop();
while(!st.empty() && st.top() > num){
st.pop(); // 抛弃,直到遇到刚好st[j] <= num
}
st.push(head);
}
else{
st.push(num);
}
}
return st.size();
}
};
Java Code:
class Solution {
public int maxChunksToSorted(int[] arr) {
LinkedList<Integer> stack = new LinkedList<Integer>();
for(int num : arr) {
if(!stack.isEmpty() && num < stack.getLast()) {
int head = stack.removeLast();
while(!stack.isEmpty() && num < stack.getLast()) stack.removeLast();
stack.addLast(head);
}
else stack.addLast(num);
}
return stack.size();
}
}
复杂度分析
令 n 为数组长度。
768. 最多能完成排序的块 II
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/max-chunks-to-make-sorted-ii/
前置知识
题目描述
arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。
我们最多能将数组分成多少块?
示例 1:
输入: arr = [5,4,3,2,1] 输出: 1 解释: 将数组分成2块或者更多块,都无法得到所需的结果。 例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。 示例 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]之间。