Design
Big O
Design a stock api
Design a stock api
class System { // assume time being used is unique
public:
int getMax() {} //O(1)
int getMin() {} //O(1)
int getRecent() {} //O(1)
void add(long time, int price) {}
void update(long time, int price) {}
void remove(long time) {}
private:
};
Design a stock api
int getMax() {} //O(1) ?
Data structure?
Design a stock api
int getMax() {} //O(1) ?
Data structure?
Array,
Linked list,
Tree,
Queue,
Stack,
Graph
HashMap
Heap
Design a stock api
int getMax() {} //O(1) ?
Data structure?
sorted Array,
sorted Linked list,
binary Tree,
Queue,
Stack,
Graph
HashMap
Heap
Design a stock api
int getMin() {} //O(1) ?
Data structure?
sorted Array,
sorted Linked list,
binary Tree,
Queue,
Stack,
Graph
HashMap
Heap
Design a stock api
int getRecent() {} //O(1) ?
Data structure?
sorted Array,
sorted Linked list,
binary Tree,
Queue,
Stack,
Graph
HashMap
Heap
Design a stock api
void add(long time, int price) {}
void update(long time, int price) {}
void remove(long time) {}
TimeStamp
Price
Design a stock api
void add(long time, int price) {}
void update(long time, int price) {}
void remove(long time) {}
TimeStamp
Price
ordered!(sorted)
Design a stock api
TimeStamp and Price ordered!(sorted)
two way:
1, sorted algorithm
2, sorted structure
sort algorithm
sort structure
Design a stock api
TimeStamp and Price ordered!(sorted)
two way:
1, sorted algorithm (n log n for every operation)
2, sorted structure (log n for every operation)
Design a stock api
TimeStamp and Price ordered!(sorted)
two way:
1, sorted algorithm (n log n for every operation)
2, sorted structure (log n for every operation)
heap, Set
Design a stock api
Component:
1, hash map O(1) time
2, sorted structure Set O(log n) time
How to combine them?
Design a stock api
Component:
1, hash map O(1) time
2, sorted structure Set O(log n) time
How to combine them?
iterator, pair
class System {
private:
unordered_map<long,pair<set<pair<int,long>::iterator,set<pair<long,int>::iterator>
map_;
set<pair<int,long>> prices;
set<pair<long,int>> times;
};
Key
class System {
private:
unordered_map<long,pair<set<pair<int,long>::iterator,set<pair<long,int>::iterator>
map_;
set<pair<int,long>> prices;
set<pair<long,int>> times;
public:
void add(long time, int price) {
auto it1 = prices.insert(make_pair(price, time)).first;
auto it2 = times.insert(make_pair( time,price)).first;
map_[time] = make_pair(it1,it2);
}
void update(long time, int price){
prices.erase(map_[time].first);
times.erase(map_[time].second)
add(time, price);
}
void remove(long time){
prices.erase(map_[time].first);
times.erase(map_[time].second)
map_.erase(time);
}
int getMostRecent(){
return times.rbegin()->second;
}
int getMinPrice(){
return prices.begin()->first;
}
int getMaxPrice(){
return prices.rbegin()->first;
}
};
class System { // assume time being used is unique
public:
int getMax() {
return priceIndex_.rbegin()->first;
}
int getMin() {
return priceIndex_.begin()->first;
}
int getRecent() {
return timeIndex_.rbegin()->second->second;
}
void add(long time, int price) {
// assume the time being added here is a distinct value
const auto& it = list_.emplace(list_.end(), time, price);
timeIndex_[time] = it;
priceIndex_[price] += 1;
}
void update(long time, int price) {
// assume the time being updated here exists
auto& it = timeIndex_[time];
auto& oldPrice = it->second;
if (--priceIndex_[oldPrice] == 0) {
priceIndex_.erase(oldPrice);
}
oldPrice = price;
priceIndex_[oldPrice] += 1;
}
void remove(long time) {
// assume the time being updated here exists
auto& it = timeIndex_[time];
int price = it->second;
list_.erase(it);
timeIndex_.erase(time);
if (--priceIndex_[price] == 0) {
priceIndex_.erase(price);
}
}
private:
list<pair<long, int>> list_;
map<long, list<pair<long, int>>::iterator> timeIndex_;
map<int, int> priceIndex_;
};
Design an array api
Design an array api
Get, Set, SetAll // All operation is O(1)
Get(4) -> get element at index 4
Set(index, value);
SetAll(5) -> set all element to 5
class Array{
private:
public:
Status Get(int index){}
void Set(int index, int val){}
void SetAll(int val){}
};
Design an array api
Get, Set, SetAll // All operation is O(1)
Get(4) -> get element at index 4
Set(index, value);
SetAll(5) -> set all element to 5
class Array{
private:
public:
Status Get(int index){}
void Set(int index, int val){}
void SetAll(int val){}
};
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
Design an array api
Get, Set, SetAll // All operation is O(1)
Get(4) -> get element at index 4
Set(index, value);
SetAll(5) -> set all element to 5
class Array{
private:
public:
Status Get(int index){}
void Set(int index, int val){}
void SetAll(int val){}
};
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
What's the key?
Design an array api
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
What's the key?
similar to stock?
Order?
Design an array api
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
What's the key?
O(1) operation time?
structure?
algorithm?
Design an array api
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
What's the key?
X O(1) operation time?
X structure?
X algorithm?
Add dimension
Design an array api
Get? traversal all element?
Set?traversal all element?
SetAll?traversal all element?
What's the key?
Add dimension
TIMESTAMP
Design an array api
update TIMESTAMP
during every operation
O(1)
Design an array api
update TIMESTAMP
during every operation
O(1)
Get based on timestamp
Set based on timestamp
SetAll base on timestamp
Design an array api
Get based on timestamp
Set based on timestamp
SetAll base on timestamp
Node{
int value;
int version; // timestamp
}
Get, Set, SetAll // All operation is O(1)
class Status
class node{
int value;
int version;
}
class Array{
private:
int size;
vector<node> nums;
node setAll;
int timestamp
public:
Array(int sz): size(sz), timestamp(0) {
nums.resize(sz);
}
Status Get(int index){
if (nums[index].version > setAll.version) return nums[index].value;
else return setAll.value;
}
void Set(int index, int val){
nums[index].value = val;
nums[index].version = timestamp++;
}
void SetAll(int val){
setAll.value = val;
setAll.version = timestamp++;
}
};
LRU cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
Could you do both operations in O(1) time complexity?
LRUCache cache = new LRUCache( 2 /* capacity */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // returns 1 cache.put(3, 3); // evicts key 2 cache.get(2); // returns -1 (not found) cache.put(4, 4); // evicts key 1 cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4
LRUCache cache = new LRUCache( 2 /* capacity */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // returns 1 cache.put(3, 3); // evicts key 2 cache.get(2); // returns -1 (not found) cache.put(4, 4); // evicts key 1 cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4
Key
data structure:
Hashtable(O(1)) + Double linked list (O(1))
class DLinkedNode {
int key;
int value;
DLinkedNode pre;
DLinkedNode post;
}
/**
* Always add the new node right after head;
*/
private void addNode(DLinkedNode node){
node.pre = head;
node.post = head.post;
head.post.pre = node;
head.post = node;
}
/**
* Remove an existing node from the linked list.
*/
private void removeNode(DLinkedNode node){
DLinkedNode pre = node.pre;
DLinkedNode post = node.post;
pre.post = post;
post.pre = pre;
}
/**
* Move certain node in between to the head.
*/
private void moveToHead(DLinkedNode node){
this.removeNode(node);
this.addNode(node);
}
// pop the current tail.
private DLinkedNode popTail(){
DLinkedNode res = tail.pre;
this.removeNode(res);
return res;
}
Double Linked List
private Hashtable<Integer, DLinkedNode>
cache = new Hashtable<Integer, DLinkedNode>();
private int count;
private int capacity;
private DLinkedNode head, tail;
public LRUCache(int capacity) {
this.count = 0;
this.capacity = capacity;
head = new DLinkedNode();
head.pre = null;
tail = new DLinkedNode();
tail.post = null;
head.post = tail;
tail.pre = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if(node == null){
return -1; // should raise exception here.
}
// move the accessed node to the head;
this.moveToHead(node);
return node.value;
}
public void set(int key, int value) {
DLinkedNode node = cache.get(key);
if(node == null){
DLinkedNode newNode = new DLinkedNode();
newNode.key = key;
newNode.value = value;
this.cache.put(key, newNode);
this.addNode(newNode);
++count;
if(count > capacity){
// pop the tail
DLinkedNode tail = this.popTail();
this.cache.remove(tail.key);
--count;
}
}else{
// update the value.
node.value = value;
this.moveToHead(node);
}
}
class LRUCache{
private:
int _capacity;
list<pair<int,int>> items;
unordered_map<int,list<pair<int,int>>::iterator> cache;
public:
LRUCache(int capacity):_capacity(capacity) {}
int get(int key) {
auto it = cache.find(key);
if(it==cache.end()) return -1;
else{
items.splice(items.begin(), items, cache[key]);
return cache[key]->second;
}
}
void set(int key, int value) {
auto it = cache.find(key);
if(it!=cache.end()){
cache[key]->second = value;
items.splice(items.begin(), items, cache[key]);
}
else{
if((int)cache.size()==_capacity){
cache.erase(items.back().first);
items.pop_back();
}
items.push_front(make_pair(key,value));
cache[key] = items.begin();
}
}
};
C++
Copyright © 直通硅谷
http://www.zhitongguigu.com/
Homework
Copyright © 直通硅谷
http://www.zhitongguigu.com/
Homework
[GoValley-201612] Data Structure Design
By govalley201612
[GoValley-201612] Data Structure Design
- 1,030