LintCode Memcache
2016-06-23 07:20
701 查看
原题网址:http://www.lintcode.com/en/problem/memcache/
Implement a memcache which support the following features:
if key does not exist.
in memcache with a time to live (ttl). The key will be valid from curtTime to curtTime + ttl - 1 and it will be expired after ttl seconds. if ttl is 0, the key lives forever until out of memory.
by delta return the new value. Return 2147483647 if key does not exist.
by delta return the new value. Return 2147483647 if key does not exist.
It's guaranteed that the input is given with increasing
Have you met this question in a real interview?
Yes
Clarification
Actually, a real memcache server will evict keys if memory is not sufficient, and it also supports variety of value types like string and integer. In our case, let's make it simple, we can assume that we have enough
memory and all of the values are integers.
Search "LRU" & "LFU" on google to get more information about how memcache evict data.
Try the following problem to learn LRU cache:
http://www.lintcode.com/problem/lru-cache
Example
方法:使用哈希映射保存键值对,使用有序映射保存时间戳数据。
public class Memcache {
private Map<Integer, Cache> map = new HashMap<>();
private TreeMap<Integer, List<Cache>> tm = new TreeMap<>();
public Memcache() {
// Initialize your data structure here.
}
private void expire(int curtTime) {
SortedMap<Integer, List<Cache>> hm = tm.headMap(curtTime);
for(int key : hm.keySet()) {
for(Cache cache : hm.get(key)) {
map.remove(cache.key);
}
tm.remove(key);
}
}
public int get(int curtTime, int key) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
return cache.val;
}
public void set(int curtTime, int key, int value, int ttl) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) {
cache = new Cache(key, value, ttl == 0 ? Integer.MAX_VALUE : curtTime + ttl - 1);
map.put(key, cache);
List<Cache> list = tm.get(cache.ttl);
if (list == null) {
list = new ArrayList<Cache>();
tm.put(cache.ttl, list);
}
list.add(cache);
} else {
cache.val = value;
List<Cache> list = tm.get(cache.ttl);
for(int i = 0; i < list.size(); i++) {
if (list.get(i).key == key) {
list.remove(i);
break;
}
}
cache.ttl = ttl == 0 ? Integer.MAX_VALUE : curtTime + ttl - 1;
list = tm.get(cache.ttl);
if (list == null) {
list = new ArrayList<Cache>();
tm.put(cache.ttl, list);
}
list.add(cache);
}
}
public void delete(int curtTime, int key) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return;
List<Cache> list = tm.get(cache.ttl);
for(int i = 0; i < list.size(); i++) {
if (list.get(i).key == key) {
list.remove(i);
break;
}
}
map.remove(key);
}
public int incr(int curtTime, int key, int delta) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
cache.val += delta;
return cache.val;
}
public int decr(int curtTime, int key, int delta) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
cache.val -= delta;
return cache.val;
}
}
class Cache {
int key;
int val;
int ttl;
Cache(int key, int val, int ttl) {
this.key = key;
this.val = val;
this.ttl = ttl;
}
}
Implement a memcache which support the following features:
get(curtTime, key). Get the key's value, return 2147483647
if key does not exist.
set(curtTime, key, value, ttl). Set the key-value pair
in memcache with a time to live (ttl). The key will be valid from curtTime to curtTime + ttl - 1 and it will be expired after ttl seconds. if ttl is 0, the key lives forever until out of memory.
delete(curtTime, key). Delete the key.
incr(curtTime, key, delta). Increase the key's value
by delta return the new value. Return 2147483647 if key does not exist.
decr(curtTime, key, delta). Decrease the key's value
by delta return the new value. Return 2147483647 if key does not exist.
It's guaranteed that the input is given with increasing
curtTime.
Have you met this question in a real interview?
Yes
Clarification
Actually, a real memcache server will evict keys if memory is not sufficient, and it also supports variety of value types like string and integer. In our case, let's make it simple, we can assume that we have enough
memory and all of the values are integers.
Search "LRU" & "LFU" on google to get more information about how memcache evict data.
Try the following problem to learn LRU cache:
http://www.lintcode.com/problem/lru-cache
Example
get(1, 0) >> 2147483647 set(2, 1, 1, 2) get(3, 1) >> 1 get(4, 1) >> 2147483647 incr(5, 1, 1) >> 2147483647 set(6, 1, 3, 0) incr(7, 1, 1) >> 4 decr(8, 1, 1) >> 3 get(9, 1) >> 3 delete(10, 1) get(11, 1) >> 2147483647 incr(12, 1, 1) >> 2147483647
方法:使用哈希映射保存键值对,使用有序映射保存时间戳数据。
public class Memcache {
private Map<Integer, Cache> map = new HashMap<>();
private TreeMap<Integer, List<Cache>> tm = new TreeMap<>();
public Memcache() {
// Initialize your data structure here.
}
private void expire(int curtTime) {
SortedMap<Integer, List<Cache>> hm = tm.headMap(curtTime);
for(int key : hm.keySet()) {
for(Cache cache : hm.get(key)) {
map.remove(cache.key);
}
tm.remove(key);
}
}
public int get(int curtTime, int key) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
return cache.val;
}
public void set(int curtTime, int key, int value, int ttl) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) {
cache = new Cache(key, value, ttl == 0 ? Integer.MAX_VALUE : curtTime + ttl - 1);
map.put(key, cache);
List<Cache> list = tm.get(cache.ttl);
if (list == null) {
list = new ArrayList<Cache>();
tm.put(cache.ttl, list);
}
list.add(cache);
} else {
cache.val = value;
List<Cache> list = tm.get(cache.ttl);
for(int i = 0; i < list.size(); i++) {
if (list.get(i).key == key) {
list.remove(i);
break;
}
}
cache.ttl = ttl == 0 ? Integer.MAX_VALUE : curtTime + ttl - 1;
list = tm.get(cache.ttl);
if (list == null) {
list = new ArrayList<Cache>();
tm.put(cache.ttl, list);
}
list.add(cache);
}
}
public void delete(int curtTime, int key) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return;
List<Cache> list = tm.get(cache.ttl);
for(int i = 0; i < list.size(); i++) {
if (list.get(i).key == key) {
list.remove(i);
break;
}
}
map.remove(key);
}
public int incr(int curtTime, int key, int delta) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
cache.val += delta;
return cache.val;
}
public int decr(int curtTime, int key, int delta) {
// Write your code here
expire(curtTime);
Cache cache = map.get(key);
if (cache == null) return Integer.MAX_VALUE;
cache.val -= delta;
return cache.val;
}
}
class Cache {
int key;
int val;
int ttl;
Cache(int key, int val, int ttl) {
this.key = key;
this.val = val;
this.ttl = ttl;
}
}
相关文章推荐
- LintCode Majority Number iii
- LintCode-最大数
- lintCode Intersection of Two Arrays II
- Intersection of Two Arrays
- Subtree
- LintCode --number-of-airplanes-in-the-sky(数飞机)
- LintCode --invert-binary-tree(翻转二叉树)
- LintCode --find-the-missing-number(寻找缺失的数)
- LintCode--best-time-to-buy-and-sell-stock(买卖股票的最佳时机)
- LintCode--best-time-to-buy-and-sell-stock-ii(买卖股票的最佳时机 II)
- lintcode之不同子序列数 + 序列II
- lintcode之快速幂
- lintcode删除排序数组中的重复数字 II
- lintcode之数组划分
- leetcode之三数之和 II
- lintcode之 数组剔除元素后的乘积
- lintcode之 合并排序数组 II
- lintcode 之子数组之和
- lintcode之最长公共前缀
- lintcode 之 最长公共子串