Max Chunks To Make Sorted II LT768
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:
arr
will have length in range[1, 2000]
.arr[i]
will be an integer in range[0, 10**8]
.
Similar to previous discussion, we can use minRight to record the min value from the right, as long as left elements are smaller or equal than the right elements, there could be a new chunk.
Time complexity: O(n)
Space complexity: O(n)
public class SolutionLT768 { public int maxChunksToSorted(int[] arr) { if(arr == null) return 1; int sz = arr.length; int[] rightMin = new int[sz]; rightMin[sz-1] = arr[sz-1]; for(int i = sz-2; i >= 0; --i) { rightMin[i] = Math.min(rightMin[i+1], arr[i]); } int currMax = arr[0]; int count = 1; for(int i = 0; i < sz -1; ++i) { currMax = Math.max(currMax, arr[i]); if(currMax <= rightMin[i+1]) { ++count; } } return count; } public static void main(String[] args) { SolutionLT768 subject = new SolutionLT768(); int[] testData1 = {5, 4, 3, 2, 1}; int[] testData2 = {2, 1, 3, 4, 4}; System.out.println(subject.maxChunksToSorted(testData1)); System.out.println(subject.maxChunksToSorted(testData2)); } }
Using stack to record the max element of each chunk, if the next element is smaller than the max element on the stack, need to merge the chunk by poping out max elements on previous chunks; else if the next element is bigger, push it to the stack. Hence, the stack keeps the max element of the new chunk or merged chunk.
Time complexity: O(n)
Space complexity: O(n)
public class SolutionLT768 { public int maxChunksToSorted(int[] arr) { Deque<Integer> maxStack = new LinkedList<>(); for(int num: arr) { int currMax = maxStack.isEmpty()? num: Math.max(num, maxStack.peek()); while(!maxStack.isEmpty() && maxStack.peek() > num) { maxStack.pop(); } maxStack.push(currMax); } return maxStack.size(); } }
Previously, based on the observation arr[i] = i, this won't work for duplicates, to fix the duplicates, we can use stable sort to get the index and then use the index array as the problem 764.
[2, 1, 4, 4, 3, 5, 7, 6] -> [1, 2, 3, 4, 4, 5, 6, 7] -> [1, 0, 4, 2, 3, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7]
Time complexity: O(nlgn)
Space complexity: O(n)
class Solution { public int maxChunksToSorted(int[] arr) { List<Integer> stableSortedIndexes = new ArrayList<>(); for(int i = 0; i < arr.length; ++i) { stableSortedIndexes.add(i); } Comparator<Integer> comparator = (o1, o2) -> { return arr[o1] - arr[o2]; }; Collections.sort(stableSortedIndexes, comparator); int currMax = stableSortedIndexes.get(0); int count = 0; for(int i = 0; i < stableSortedIndexes.size(); ++i) { currMax = Math.max(currMax, stableSortedIndexes.get(i)); if(currMax == i) { ++count; } } return count; } }