2020京东秋招笔试题1 && LeetCode768 最多能完成排序的块II

题目:
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();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值