题解
- 题目没有解释清楚。不是最终的状态是恰好,而是每一次停放是恰好停放在其左边或者右边。
- 另外,题目没有说明,应该是每一次需要停的车是x,已经停好的车是y。
综上,需要一个查找和插入都是O(1)复杂度的数据结构。—> hash +双向链表
实现
- 使用顺序表记录链表的地址,从而实现O(1)的hash查找
- 使用双向链表进行O(1)的插入
双向链表需要注意的点:
- 插入第一个结点的时候需要判断空
- 前插的时候,需要看是否插入第一个
a. 如果是,不用指向自己
b. 如果不是,头结点需要更新 - 向后插的时候,需要看是否插入最后一个,如果是,不用更新后一个的前结点。
- cpp版本
//STl自行车停放
#include<bits/stdc++.h>
using namespace std;
long long n,x,a,b,c;
list<int> :: iterator loc[100003];
int main(){
long long i; // 内存地址,使用long long 防止爆int
list<int> L;
cin>>n>>x;
L.push_back(x); //把x插入
loc[x] = L.begin(); //x的地址为链表的起始值
list<int> :: iterator temp;
for(int i=1;i<=n-1;i++){
cin>>a>>b>>c; //a为代插元素,b为已有元素,c为方向
temp = loc[b]; //b的地址给temp
if(c==0){//左边插入
L.insert(temp,a);
loc[a] = --temp;
}
else{
//右边插入
L.insert(++temp,a);
loc[a] =--temp;
}
}
for(list<int>::iterator it = L.begin() ; it!=L.end() ; it++)
cout << *it <<" ";
}
- java实现
import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
/**
* @author: Zekun Fu
* @date: 2022/12/19 23:45
* @Description:
*/
public class Main{
/**
* 双向链表的实现
*
* @author liyanan
* @date 2020/1/2 13:16
*/
public static class SNode<T> {
/**
* 存储数据
*/
public T data;
/**
* 指向当前结点的前一个结点
*/
public SNode<T> pre;
/**
* 指向当前结点的下一个节点
*/
public SNode<T> next;
public SNode() {
}
public SNode(T data) {
this.data = data;
}
}
public static class DoubleLinkedList<T> {
/**
* 双向链表的头结点,存储第一个有效结点的基地址
*/
private SNode<T> head;
/**
* 双向链表的有效结点数量
*/
private int size;
public DoubleLinkedList() {
head = null;
size = 0;
}
public int getSize() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
/**
* 插入结点到双向链表末尾
*
* @param newNode
*/
public void addLast(SNode<T> newNode) {
if (isEmpty()) {
head = newNode;
head.next = null;
head.pre = null;
size++;
} else {
SNode<T> temp = head;
// 找到双向链表最后一个有效结点
while (temp.next != null) {
temp = temp.next;
}
// 将新结点加入双向链表
addAfter(temp, newNode);
}
}
/**
* 将新的节点插入到指定节点后
*
* @param preNode 指定节点
* @param newNode 新的节点
*/
public void addAfter(SNode<T> preNode, SNode<T> newNode) {
// 要插入到链表末尾时,不需要维护下一个结点的前驱指针
if (preNode.next != null) {
preNode.next.pre = newNode;
}
newNode.next = preNode.next;
newNode.pre = preNode;
preNode.next = newNode;
size++;
}
/**
* 将结点插入到新结点前
*/
public void addPre(SNode<T> afterNode, SNode<T> newNode) {
// 要插入到链表第一个结点时候,不用维护前一个的后继
if (afterNode.pre != null) {
afterNode.pre.next = newNode;
} else head = newNode;
newNode.pre = afterNode.pre;
newNode.next = afterNode;
afterNode.pre = newNode;
size++;
}
/**
* 删除数据域为指定值的元素
*
* @param e
*/
public void del(T e) {
SNode<T> temp = head;
while (temp != null) {
if (temp.data.equals(e)) {
// 维护 head,head 永远指向双向链表第一个有效结点
temp.next.pre = temp.pre;
if (temp == head) {
head = head.next;
head.pre = null;
} else {
temp.pre.next = temp.next;
}
return;
}
// temp 向后移
temp = temp.next;
}
}
/**
* 删除指定位置的结点
*
* @param k
*/
public void del(int k) {
SNode<T> delNode = find(k);
delNode.next.pre = delNode.pre;
if (delNode == head) {
head = head.next;
head.pre = null;
} else {
delNode.pre.next = delNode.next.next;
}
}
public SNode<T> findO(T x) {
SNode<T>p = head;
while (p != null && !p.data.equals(x)) p = p.next;
assert p != null;
return p;
}
/**
* 找到双向链表第 k 个结点
*
* @param k k 从 0 开始
* @return
*/
public SNode<T> find(int k) {
if (k > size || k < 0) {
throw new RuntimeException("传入的参数 k 必须大于等于零并且小于等于链表的长度 size");
}
int cnt = 0;
SNode<T> t = head;
while (cnt != k) {
cnt++;
t = t.next;
}
return t;
}
/**
* 打印单链表所有有效节点
*
* @return
*/
public String printAll() {
StringBuilder sb = new StringBuilder();
SNode<T> temp = head;
while (temp != null) {
sb.append(temp.data);
sb.append(" ");
temp = temp.next;
}
return sb.toString();
}
}
public static void main(String[] args) throws Exception{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
HashMap<Integer, SNode<Integer>>loc = new HashMap<>();
int n = Integer.parseInt(in.readLine());
int x = Integer.parseInt(in.readLine());
DoubleLinkedList<Integer> list = new DoubleLinkedList<>();
// HashSet<Integer>set = new HashSet<>();
SNode<Integer> cur = new SNode<>(x);
loc.put(x, cur);
list.addLast(cur);
for (int i = 0; i < n - 1; i++) {
String[] input = in.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
int c = Integer.parseInt(input[2]);
// b是已知结点,
SNode<Integer> preNode = loc.get(b);
cur = new SNode<>(a);
loc.put(a, cur);
if (c == 1) {
// 把当前结点放在前一个结点的右边。
list.addAfter(preNode, cur);
}
else {
// 把当前结点放在前一个结点的左边
list.addPre(preNode, cur);
}
}
// out.write(list.printAll());
// System.out.println();
System.out.println(list.printAll());
}
}