欢迎访问我的CCF认证解题目录
题目描述
思路过程
代码1:
- 新建一个num数组模拟钥匙盒,新建一个类Key来表示借和还的信息,key为编号,time为处理时间,type为类型(1表示借,-1表示还)
- 借的时候直接遍历数组即可,拿钥匙的时候标记为-1,表示钥匙盒该位置为空。
- 还的时候遍历数组找到-1,填入即可
代码2:
- 代码1的借和还时间复杂度都为
n
,可以借助堆和映射来优化到log(n)
- map映射规则:钥匙编号->下标
- 堆:使用最小堆存储空位置
代码1
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] num = new int[n];
PriorityQueue<Key> p = new PriorityQueue<>(new Comparator<Key>() {
@Override
public int compare(Key o1, Key o2) {
if ( o1.time != o2.time ) {//时间升序
return o1.time - o2.time;
} else if ( o1.type != o2.type ) {//先还后借
return o1.type - o2.type;
} else {//编号升序
return o1.key - o2.key;
}
}
});
for ( int i = 0; i < num.length; i++ ) num[i] = i+1;//开始的时候编号从小到大
for ( int i = 0; i < k; i++ ) {
int key = in.nextInt(), st = in.nextInt(), time = in.nextInt();
p.add(new Key(key, st, 1));//借
p.add(new Key(key, st+time, -1));//还
}
while ( !p.isEmpty() ) {
Key key = p.poll();
if ( key.type == 1 ) {//借
for (int i = 0; i < num.length; i++) {
if ( key.key == num[i] ) {
num[i] = -1;//-1表示位置没有钥匙
break;
}
}
} else {
for ( int i = 0; i < num.length; i++ ) {
if ( num[i] == -1 ) {
num[i] = key.key;
break;
}
}
}
}
for ( int i = 0; i < num.length; i++ ) {
System.out.print(num[i]+" ");
}
}
}
class Key {
int key, time, type;//1表示借,-1表示还
public Key(int key, int time, int type) {
this.key = key;
this.time = time;
this.type = type;
}
}
代码2
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] num = new int[n];
PriorityQueue<Key> p = new PriorityQueue<>(new Comparator<Key>() {
@Override
public int compare(Key o1, Key o2) {
if ( o1.time != o2.time ) {//时间升序
return o1.time - o2.time;
} else if ( o1.type != o2.type ) {//先还后借
return o1.type - o2.type;
} else {//编号升序
return o1.key - o2.key;
}
}
});
//优化借和还,从n->log(n)
PriorityQueue<Integer> kong = new PriorityQueue<>();//空位置
HashMap<Integer, Integer> map = new HashMap<>();//钥匙的位置,num:index
for ( int i = 0; i < num.length; i++ ) {
num[i] = i+1;//开始的时候编号从小到大
map.put(i+1, i);
}
for ( int i = 0; i < k; i++ ) {
int key = in.nextInt(), st = in.nextInt(), time = in.nextInt();
p.add(new Key(key, st, 1));//借
p.add(new Key(key, st+time, -1));//还
}
while ( !p.isEmpty() ) {
Key key = p.poll();
if ( key.type == 1 ) {//借
int index = map.get(key.key);//获取钥匙的下标
num[index] = -1;//拿走
kong.add(index);//填入空位置
} else {
int index = kong.poll();//获取空位置的下标
num[index] = key.key;//归还
map.put(key.key, index);//重新写入钥匙的位置
}
}
for ( int i = 0; i < num.length; i++ ) {
System.out.print(num[i]+" ");
}
}
}
class Key {
int key, time, type;//1表示借,-1表示还
public Key(int key, int time, int type) {
this.key = key;
this.time = time;
this.type = type;
}
}