题目描述
博艾市有一个木材厂,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的。作为厂长,你有时候会进货,有时候会出货,因此需要维护这个库存。有不超过100000 条的操作:
- 进货,格式 1 Length : 在仓库中放入一根长度为 Length(不超过) 的木材。如果已经有相同长度的木材那么输出 Already Exist 。
- 出货,格式 2 Length : 从仓库中取出长度为 Length 的木材。如果没有刚好长度的木材,取出仓库中存在的和要求长度最接近的木材。如果有多根木材。符合要求,取出比较短的一根。输出取出的木材长度。如果仓库是空的,输出 Empty 。
输入格式
一个数字
n
,表示操作的次数。接下来
n
行,每行是一个操作。
输出格式
2 操作的个数行,表示每次取出的木材长度。
样例 #1
样例输入 #1
71 11 51 32 32 32 32 3
样例输出 #1
315Empty
解题思路
本题可以利用set集合,set集合中可以按照某种规则对集合中的元素进行排序,本题利用java中的TreeSet集合来实现排序,以及利用其中的higher()和lower()方法取出严格大于给定元素的该集合中的最小和最大元素(其他语言中也有类似方法)。
代码整体执行流程:
- 循环从1到n,每次获取输入的操作op和长度len。
- 如果操作op为1,则尝试将长度len添加到TreeSet ts中,如果已经存在则输出"Already Exist"。
- 如果操作op不为1,则判断TreeSet ts是否为空,如果是则输出"Empty";否则继续执行以下步骤。
- 如果TreeSet ts中包含长度len,则移除该长度并输出len;否则查找比len小但最接近的值lower和比len大但最接近的值higher。
- 如果lower为null,则输出higher并移除该值;如果higher为null,则输出lower并移除该值。
- 如果同时存在lower和higher,则输出比较短的lower(题目要求),并移除该值。
- 重复上述步骤直至循环结束。
流程图
流程图仅展示一次循环的过程。
源代码
import java.util.Scanner;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
TreeSet<Integer> ts = new TreeSet<>();
for (int i = 1; i <= n; i++) {
int op = sc.nextInt();
int len = sc.nextInt();
if (op == 1) {
if (!ts.add(len))
System.out.println("Already Exist");
} else {
if (ts.isEmpty()) {
System.out.println("Empty");
} else {
if (ts.contains(len)) {
ts.remove(len);
System.out.println(len);
} else {
Integer lower = ts.lower(len);
Integer higher = ts.higher(len);
if (lower == null) {
System.out.println(higher);
ts.remove(higher);
} else if (higher == null) {
System.out.println(lower);
ts.remove(lower);
} else {
if (len - lower <= higher - len) {
System.out.println(lower);
ts.remove(lower);
} else {
System.out.println(higher);
ts.remove(higher);
}
}
}
}
}
}
}
}