forked from doocs/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.rs
122 lines (113 loc) · 3.37 KB
/
Solution.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::cell::RefCell;
use std::collections::hash_map::HashMap;
use std::rc::Rc;
struct Node {
key: i32,
value: i32,
prev: Option<Rc<RefCell<Node>>>,
next: Option<Rc<RefCell<Node>>>,
}
impl Node {
#[inline]
fn new(key: i32, value: i32) -> Node {
Node {
key,
value,
prev: None,
next: None,
}
}
}
struct LRUCache {
capacity: usize,
cache: HashMap<i32, Rc<RefCell<Node>>>,
head: Option<Rc<RefCell<Node>>>,
tail: Option<Rc<RefCell<Node>>>,
}
impl LRUCache {
fn new(capacity: i32) -> Self {
LRUCache {
capacity: capacity as usize,
cache: HashMap::new(),
head: None,
tail: None,
}
}
fn get(&mut self, key: i32) -> i32 {
if let Some(node) = self.cache.get(&key) {
let node = Rc::clone(node);
self.remove(&node);
self.push_front(&node);
let value = node.borrow().value;
value
} else {
-1
}
}
fn put(&mut self, key: i32, value: i32) {
if let Some(node) = self.cache.get(&key) {
let node = Rc::clone(node);
node.borrow_mut().value = value;
self.remove(&node);
self.push_front(&node);
} else {
let node = Rc::new(RefCell::new(Node::new(key, value)));
self.cache.insert(key, Rc::clone(&node));
self.push_front(&node);
if self.cache.len() > self.capacity {
if let Some(back) = self.pop_back() {
self.cache.remove(&back.borrow().key);
}
}
}
}
fn push_front(&mut self, node: &Rc<RefCell<Node>>) {
let mut node_borrow_mut = node.borrow_mut();
if let Some(head) = self.head.take() {
head.borrow_mut().prev = Some(Rc::clone(node));
node_borrow_mut.next = Some(head);
node_borrow_mut.prev = None;
self.head = Some(Rc::clone(node));
} else {
self.head = Some(Rc::clone(node));
self.tail = Some(Rc::clone(node));
}
}
fn remove(&mut self, node: &Rc<RefCell<Node>>) {
match (node.borrow().prev.as_ref(), node.borrow().next.as_ref()) {
(None, None) => {
self.head = None;
self.tail = None;
}
(None, Some(next)) => {
self.head = Some(Rc::clone(next));
next.borrow_mut().prev = None;
}
(Some(prev), None) => {
self.tail = Some(Rc::clone(prev));
prev.borrow_mut().next = None;
}
(Some(prev), Some(next)) => {
next.borrow_mut().prev = Some(Rc::clone(prev));
prev.borrow_mut().next = Some(Rc::clone(next));
}
}
}
fn pop_back(&mut self) -> Option<Rc<RefCell<Node>>> {
if let Some(tail) = self.tail.take() {
match tail.borrow().prev.as_ref() {
Some(prev) => {
prev.borrow_mut().next = None;
self.tail = Some(Rc::clone(prev));
}
None => {
self.head = None;
self.tail = None;
}
}
Some(tail)
} else {
None
}
}
}