[LeetCode 阿里天池专场] [贪心&单调栈] 03. 整理书架

LeetCode 阿里天池专场 03. 整理书架

原地址:https://leetcode.cn/contest/tianchi2022/problems/ev2bru/

书架上有若干本书,从左至右的书籍编号记于整型数组 order 中。为保证书籍多样性,管理员想取走一些重复编号的书籍,要求满足以下条件:

剩余书本中相同编号的书本数量均不大于 limit

  • 取走的书籍数量尽可能少
  • 由于存在多种整理方案,请返回剩余书本编号的排列为「最小排列」的方案。

注意:

  • 「最小排列」:若干数组中第一位数字最小的数组;若第一位数字相同,则为第二位数字最小的数组,以此类推。

Solution(贪心&单调栈)

题解参考:https://www.bilibili.com/video/BV1ne4y177wN

  • 字典序最小 ==> 贪心
  • 依次遍历数组,应该装入更小的,弹出更大的 ==> 单调栈
  1. 首先记录每本书的数量;
  2. 依次遍历书列表:
    • 若当前书已经入栈的数量等于 limit,则不需要再入栈,并将该书剩余数量 - 1,进行下一次遍历
    • 否则,循环判断,若当前书序号小于栈顶书的序号 && 栈顶书的剩余数量大于 limit,将栈顶书弹出,并将栈顶书已经入栈的数量 - 1,剩余栈顶书序号数量 - 1
    • 最后将当前书入栈,并将当前书已经入栈的数量 + 1

注意代码中的一个点:

  • left 记录全部的(包括栈内和还没遍历到)每种书的数量
  • counter 只记录已经入栈的每种书的数量
public int[] arrangeBookshelf(int[] order, int limit) {
	 // 每本书剩余数量
	 Map<Integer, Integer> left = new HashMap<>();
	 for (int x : order) {
	     left.put(x, left.getOrDefault(x, 0) + 1);
	 }
	 
	 Deque<Integer> stack = new LinkedList<>();
	 // 插入一个 0 作比较
	 stack.push(0);
	 
	 // 已经加入栈中的元素计数
	 Map<Integer, Integer> counter = new HashMap<>();
	
	 for (int x : order) {
		 // 遍历的同时需要保证栈里面的元素出现次数不超过 limit
	     if (counter.getOrDefault(x, 0) == limit) {
	         left.put(x, left.get(x) - 1);
	         continue;
	     }
	     // 只有当前书序号比栈顶书序号小,并且栈顶书剩余数量必须大于 limit
	     while (x < stack.peek() && left.get(stack.peek()) > limit) {
	         Integer top = stack.poll();
	         left.put(top, left.get(top) - 1);
	         counter.put(top, counter.getOrDefault(top, 0) - 1);
	     }
	     stack.push(x);
	     counter.put(x, counter.getOrDefault(x, 0) + 1);
	 }
	
	 // 弹出 0
	 stack.pollLast();
	 
	 // 存入数组
	 int[] ans = new int[stack.size()];
	 int k = ans.length;
	 while(!stack.isEmpty()) {
	     ans[--k] = stack.poll();
	 }
	 return ans;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哇咔咔负负得正

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值