「天池 X LeetCode」在线编程专场选拔赛 2022/10/22

题三:221021天池-03. 整理书架

力扣

 思路:单调栈

因为要求最小序列,并且只是去掉数组中的一些元素,并且是往后遍历才知道当前元素需要保留与否。

统计所有的元素出现的数目,记为bookCountMap,在遍历order中,我们还需要记录那些选中的数字的个数,记为usedBookMap。

1. 首先,我们判断当前元素cur是否能够入栈,如果说当前元素在之前已经用过limit次了,也就是used(cur) >= limit,那么这个时候只能放弃当前元素,并更新bookCountMap。

2. 如果当前元素cur可以入栈,那么我们还需要判断一下是否还需要移除栈顶元素top,直到能够确保最小化序列。

具体来说:

        栈顶代表着最近一个满足条件的元素,设栈顶元素为top,当前元素为cur,

        如果当前cur > top && count(top) > limit,那么此时就可以移除掉栈顶元素top了。

解释:

        因为当top的总数大于limit的时候,就说明当前这个top可以移除,也可以移除。但是我们要确保最小的序列,所以说,如果当前值cur要比top更小,那么自然可以将这些不满足条件的top都移除掉。

3. 如果当前元素cur可以入栈,且栈顶也满足条件,那么就将当前元素加入栈中。

4. 最后的结果就是栈里面保存的数据,拿出来放到数组里面就好了。

栈顶元素需要满足的条件

        栈顶元素是不可被移出的,主要有如下两种情况:

  1. top的总数要比limit小,这种情况下不能移出栈顶。
  2. 还有一种情况就是top总数来看可以被移出,但是因为top < cur,如果移出了top,那么加入cur之后,序列肯定没有之前小。

代码:

class Solution {
    public int[] arrangeBookshelf(int[] order, int limit) {
        Stack<Integer> stack = new Stack<>();
        Map<Integer, Integer> bookCountMap = new HashMap();
        Map<Integer, Integer> usedBookMap = new HashMap();
        for (int book : order) {
            bookCountMap.compute(book, (key, value) ->  value == null ? 1 : value + 1);
        }
        
        // 栈顶top需要满足, top < cur || (top > cur && count(top) <= limit)
        int top;
        for (int cur : order) {    
            
            // 如果之前已经有的book编号数量 < limit,那么可以将当前书本加进来。
            if (usedBookMap.get(cur) == null || usedBookMap.get(cur) < limit) {
                while (!stack.empty() && (cur < (top = stack.peek()) && bookCountMap.get(top) > limit)) {
                                
                    stack.pop();
                    bookCountMap.put(top, bookCountMap.get(top) - 1);
                    if (usedBookMap.get(top) != null && usedBookMap.get(top) > 0) {
                        usedBookMap.put(top, usedBookMap.get(top) - 1);
                    }
                }
                stack.push(cur);
                usedBookMap.compute(cur, (key, value) -> value == null ? 1 : value + 1);
                
            } else {
                bookCountMap.put(cur, bookCountMap.get(cur) - 1);
            }
        }
        
        int[] res = new int[stack.size()];
        for (int i = res.length - 1; i > -1; i--) {
                res[i] = stack.pop();
            
        }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值