432. All O`one Data Structure

高效数据结构设计
本文介绍了一种支持增删操作及获取最大最小值的数据结构设计方案,采用哈希表结合双向链表实现所有操作的O(1)时间复杂度。

Implement a data structure supporting the following operations:

  1. Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string.
  2. Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
  3. GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "".
  4. GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "".

Challenge: Perform all these in O(1) time complexity.

思路:因为insert和delete要O(1),所以要用HashTable,且key为cnt,value为HashSet
 * 
 * 因为getMax和getMin要O(1),那用数组,把cnt作为index行吗?
 * 这样求max还是要遍历数组,题目只要求获得max和min,
 * 应该用linkedList,插入的时候排好序,最前面的是最大的cnt,最后面是最小的cnt
 * 再用个双向链表就可以在O(1)时间取出
 * 
 * 因为JDK自带的LinkedList并不能实现O(1)的时间找到某个Node,
 * 而LinkedHashSet虽然能在O(1)时间内查找和删除,但是并不能O(1)查min,max
 * 所以还是要自己写个HashTable + double LinkedList(得自己实现)
 * 
 *  JDK为什么不自己实现一个这样的类呢??

head --- ValueNode1 ---- ValueNode2 ---- ... ---- ValueNodeN --- tail 
              |               |                       |               
            first           first                   first             
              |               |                       |               
           KeyNodeA        KeyNodeE                KeyNodeG           
              |               |                       |               
           KeyNodeB        KeyNodeF                KeyNodeH           
              |                                       |               
           KeyNodeC                                KeyNodeI           
              |                                                       
           KeyNodeD                                                   

public class AllOne {
	
	class Node {
		Node next, prev;
		int cnt = 0;
		private Node(int cnt) {
			this.cnt = cnt;
		}
		// Set<Integer> keys = new HashSet<Integer>();
	}
	
	HashMap<Integer, HashSet<String>> cnt2set = new HashMap<Integer, HashSet<String>>();
	HashMap<String, Integer> key2cnt = new HashMap<String, Integer>();
	// HashMap<String, Node> nodes = new HashMap<String, Node>();
	// LinkedList<Integer> q = new LinkedList<Integer>();
//	LinkedHashSet<Integer> q = new LinkedHashSet<Integer>();
	
	Node head = new Node(-1), tail = new Node(-1);
	Map<Integer, Node> cnt2node = new HashMap<Integer, Node>();
	
    /** Initialize your data structure here. */
    public AllOne() {
        head.next = tail;
        tail.prev = head;
    }
    
    public void inc(String key) {
    	myinc(key);
//    	try {
//    		myinc(key);
//    	} catch (Exception e) {
//    		e.printStackTrace();
//    	}
    }
    
    public void dec(String key) {
    	mydec(key);
//    	try {
//    		mydec(key);
//    	} catch (Exception e) {
//    		e.printStackTrace();
//    	}
    }
    
    /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
    public void myinc(String key) {
        if(key2cnt.containsKey(key)) {
        	int orig = key2cnt.get(key);
        	key2cnt.put(key, orig+1);	// 1. key2cnt
        	if(!cnt2set.containsKey(orig+1))	// 2. cnt2set
        		cnt2set.put(orig+1, new HashSet<String>());
        	cnt2set.get(orig).remove(key);	
        	cnt2set.get(orig+1).add(key);	
        	
        	// 3. linkedlist
        	if(!cnt2node.containsKey(orig+1)) {
        		Node t = new Node(orig+1), tt = cnt2node.get(orig);
        		t.next = tt;
        		t.prev = tt.prev;
        		tt.prev = t;
        		tt.prev.next = t;
        		cnt2node.put(orig+1, t);
        	}
        	
        	if(cnt2set.get(orig).size() == 0) {
//        		map.remove(orig);      // 可以不remove,只要在链表中把对应cnt值得node删掉就行
        		Node node = cnt2node.get(orig);
        		node.prev.next = node.next;
        		node.next.prev = node.prev;
        		cnt2node.remove(orig);
        	}
        	
        } else {
        	key2cnt.put(key, 1);
        	if(!cnt2set.containsKey(1))
        		cnt2set.put(1, new HashSet<String>());
        	cnt2set.get(1).add(key);
        	if(tail.prev.cnt != 1) {
        		Node t = new Node(1);
        		t.prev = tail.prev;
        		t.next = tail;
        		tail.prev.next = t;
        		tail.prev = t;
        		cnt2node.put(1, t);
        	}
        }
    }
    
    /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    public void mydec(String key) {
        if(!key2cnt.containsKey(key) || key2cnt.get(key) == 0)	return;
        int orig = key2cnt.get(key);
        if(orig > 1) {
        	key2cnt.put(key, key2cnt.get(key)-1);
        	cnt2set.get(orig).remove(key);
        	cnt2set.get(orig-1).add(key);
        	
        	if(!cnt2node.containsKey(orig-1)) {
        		Node t = new Node(orig-1), tt = cnt2node.get(orig);
        		t.next = tt.next;
        		t.prev = tt;
        		tt.next.prev = t;
        		tt.next = t;
        		cnt2node.put(orig-1, t);
        	}
        	
        	if(cnt2set.get(orig).size() == 0) {
        		Node node = cnt2node.get(orig);
        		node.prev.next = node.next;
        		node.next.prev = node.prev;
        		cnt2node.remove(orig);
        	}
        	
        } else {
        	key2cnt.put(key, 0);
        	cnt2set.get(orig).remove(key);
        	
        	if(cnt2set.get(1).size() == 0) {
        		Node node = cnt2node.get(1);
        		node.prev.next = node.next;
        		node.next.prev = node.prev;
        		cnt2node.remove(orig);
        	}
        }
    }
    
    /** Returns one of the keys with maximal value. */
    public String getMaxKey() {
    	if(head.next == tail)	return "";
        return cnt2set.get(head.next.cnt).iterator().next();	// 从set中获取一个数
    }
    
    /** Returns one of the keys with Minimal value. */
    public String getMinKey() {
    	if(head.next == tail)	return "";
        return cnt2set.get(tail.prev.cnt).iterator().next();	// 从set中获取一个数
    }
}


还是有bug,用try-catch也没调试出来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值