题目:
arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。
解法一:暴力法
思路:设一个值为max,记录从左到右遍历时,数组的最大值;当数组的最大值小于等于当前的数,判断之后的数是否有比数组最大值小的,如果没有,就可以从这里断开,如果有则不行
代码:
public static int getCount(int[] nums){
if(nums==null||nums.length==0) return 0;
int count=1,max=nums[0];
if(nums.length==1) return 1;
for (int i = 1; i <nums.length ; i++) {
if(nums[i]>=max){
if(get(nums,max,i+1,nums.length-1)){
count++;
}
max=nums[i];
}
}
return count;
}
public static boolean get(int[] nums,int max,int i,int j){
for (int k = i; k <=j ; k++) {
if(nums[k]<max) return false;
}
return true;
}
方法二:最大值数组
思路:创建一个数组来记录从左到右的数组最大值,我们知道,如果左边区间的最大值小于右边区间的最小值则可以从此处断开,于是我们新建个变量cmin,从右到左来记录最小值,如果最小值大于前一个的最大值数组值,就可以从这里分开
代码:
public int maxChunksToSorted(int[] arr) {
int[] max = new int[arr.length];
max[0] = arr[0];
for(int i=1; i<arr.length; i++)
max[i] = Math.max(arr[i], max[i-1]);
int cmin = Integer.MAX_VALUE, re=0;
for (int i = arr.length-1; i >=0; i--) {
// 确切地说,cmin记录的是arr[i+1]到最后一个数之间的最小值
// 如果cmin >= max[i], 则i这里就是一个分割点
if(cmin >= max[i])
re++;
cmin = Math.min(cmin,arr[i]);
}
return re;
}
第三种:辅助栈法
思路:遍历数组 arr 中的每个数字num;
(1)当栈 stack 不为空且数字num小于栈顶值时://除去比它小的排序块的最大值
栈顶 pop 出栈,并保存栈顶值为head;
当stack不为空且数字num小于栈顶值:循环栈顶 poppop 出栈;
将保存的栈顶值head重新 pushpush 入栈;
(2)当栈stack为空或数字num大于等于栈顶值时:
将num数字 pushpush 入栈。
(3)遍历完成后,栈中保存 所有排序的块中的最大值 ,因此返回栈stack长度即可获得排序块数量。
代码:
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();
}