structure

LRU缓存

import java.util.HashMap;  
import java.util.Map;  
  
class LRUCache {  
  
    private Map<Integer,Node> map;  
    private DoubleList cache;  
    private int capacity;  
  
    public LRUCache(int capacity){  
        map = new HashMap<>();  
        cache = new DoubleList();  
        this.capacity = capacity;  
    }  
  
    public int get(int key){  
        if(!map.containsKey(key)){  
            return -1;  
        }  
        int val = map.get(key).val;  
        //利用put方法将数据提前  
        put(key,val);  
        return val;  
    }  
  
    public void put(int key,int val){  
        Node node = new Node(key,val);  
        if(map.containsKey(key)){  
            cache.remove(map.get(key));  
            cache.addFirst(node);  
            //更新map中对应的数据  
            map.put(key,node);  
        }else{  
            if(capacity==cache.size()){  
                Node last = cache.removeLast();  
                map.remove(last.key);  
            }  
            cache.addFirst(node);  
            map.put(key,node);  
        }  
  
    }  
}  
/**双向链表节点类*/  
class Node{  
    int key;  
    int val;  
    Node prev;  
    Node next;  
    public Node(int key,int val){  
        this.key=key;  
        this.val=val;  
    }  
}  
  
/**  
 * 双向链表的简单操作实现  
 * @author 奥特曼打小怪兽  
 */  
class DoubleList {  
  
    private Node head;  
    private Node tail;  
    private int size;  
  
    public DoubleList(){  
        head = new Node(0,0);  
        tail = new Node(0,0);  
        head.next=tail;  
        tail.prev=head;  
        size=0;  
    }  
  
    public void addFirst(Node node){  
        node.next = head.next;  
        node.prev = head;  
        head.next.prev = node;  
        head.next = node;  
        size++;  
    }  
  
    public void remove(Node node){  
        node.prev.next = node.next;  
        node.next.prev = node.prev;  
        size--;  
    }  
  
    /**删除最后一个节点,并返回该节点*/  
    public Node removeLast(){  
        if(tail.prev==head){  
            return null;  
        }  
        Node last = tail.prev;  
        remove(last);  
        return last;  
    }  
  
    public int size(){  
        return size;  
    }  
}

LFU

class Node{  
    int key;  
    int value;  
    int freq=1;  
  
    public Node(){}  
  
    public Node(int key,int value){  
        this.key=key;  
        this.value = value;  
    }  
}  
class LFUCache {  
  
    /**内容缓存*/  
    private Map<Integer,Node> cache;  
    /**存储每个频次对应的双向链表*/  
    private Map<Integer, LinkedHashSet<Node>> freqMap;  
    /**缓存容量*/  
    private int capacity;  
    /**记录最小频次*/  
    private int minFreq;  
    /**记录缓存中的数据个数*/  
    private int size;  
  
    public LFUCache(int capacity) {  
        cache = new HashMap<>(capacity);  
        freqMap = new HashMap<>();  
        this.capacity = capacity;  
    }  
  
    /**  
     * 获得key对应的值  
     * @param key  
     * @return  
     */  
    public int get(int key) {  
        Node node = cache.get(key);  
        if(node==null){  
            return -1;  
        }  
        freqInc(node);  
        return node.value;  
    }  
  
    /**  
     * 存入新的键值对  
     * 如果键已存在,则变更其值;如果键不存在,请插入键值对。  
     * 当缓存达到其容量时。则应该在插入新项之前,使最不经常使用的项无效。  
     * 在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除最久未使用的键。  
     * @param key  
     * @param value  
     */  
    public void put(int key, int value) {  
        if(capacity==0){  
            return;  
        }  
        Node node = cache.get(key);  
        if(node!=null){  
            node.value = value;  
            freqInc(node);  
        }else{  
            if(size==capacity){  
                Node deadNode = deleteNode();  
                cache.remove(deadNode.key);  
                size--;  
            }  
            Node newNode = new Node(key,value);  
            cache.put(key,newNode);  
            addNode(newNode);  
            size++;  
        }  
  
    }  
  
    /**  
     * 更新频次以及最小值  
     * @param node  
     */  
    private void freqInc(Node node){  
        //从原freq对应的set中移除掉node,并更新minFreq  
        int freq = node.freq;  
        LinkedHashSet<Node> set = freqMap.get(freq);  
        set.remove(node);  
        if(freq==minFreq&&set.size()==0){  
            minFreq = freq+1;  
        }  
        //加入新的freq对应的双向链表  
        node.freq++;  
        LinkedHashSet<Node> newSet = freqMap.get(freq+1);  
        if(newSet==null){  
            newSet = new LinkedHashSet<>();  
            freqMap.put(freq+1,newSet);  
        }  
        newSet.add(node);  
    }  
  
    /**  
     * 添加一个节点  
     * @param node  
     */  
    private void addNode(Node node){  
        LinkedHashSet<Node> set = freqMap.get(1);  
        if(set==null){  
            set = new LinkedHashSet<>();  
            freqMap.put(1,set);  
        }  
        set.add(node);  
        minFreq = 1;  
    }  
  
    /**  
     * 删除一个节点,即清除掉一个最久未使用数据  
     * @return  
     */  
    private Node deleteNode(){  
        LinkedHashSet<Node> set = freqMap.get(minFreq);  
        Node deadNode = set.iterator().next();  
        set.remove(deadNode);  
        return deadNode;  
    }  
}

skipList

import java.util.Random;

class SkipListNode {
    int value;
    SkipListNode[] next;

    public SkipListNode(int value, int level) {
        this.value = value;
        this.next = new SkipListNode[level];
    }
}

public class SkipList {
    private static final int MAX_LEVEL = 16;
    private static final double PROBABILITY = 0.5;
    private int levelCount = 1;
    private SkipListNode head = new SkipListNode(-1, MAX_LEVEL);
    private Random random = new Random();

    public SkipListNode find(int value) {
        SkipListNode p = head;
        for (int i = levelCount - 1; i >= 0; i--) {
            while (p.next[i] != null && p.next[i].value < value) {
                p = p.next[i];
            }
        }
        if (p.next[0] != null && p.next[0].value == value) {
            return p.next[0];
        }
        return null;
    }

    public void insert(int value) {
        int level = randomLevel();
        SkipListNode newNode = new SkipListNode(value, level);
        SkipListNode[] update = new SkipListNode[level];
        SkipListNode p = head;
        for (int i = level - 1; i >= 0; i--) {
            while (p.next[i] != null && p.next[i].value < value) {
                p = p.next[i];
            }
            update[i] = p;
        }
        for (int i = level - 1; i >= 0; i--) {
            newNode.next[i] = update[i].next[i];
            update[i].next[i] = newNode;
        }
        if (levelCount < level) {
            levelCount = level;
        }
    }

    public void delete(int value) {
        SkipListNode[] update = new SkipListNode[levelCount];
        SkipListNode p = head;
        for (int i = levelCount - 1; i >= 0; i--) {
            while (p.next[i] != null && p.next[i].value < value) {
                p = p.next[i];
            
            }
            update[i] = p;
        }
        if (p.next[0] != null && p.next[0].value == value) {
            for (int i = levelCount - 1; i >= 0; i--) {
                if (update[i].next[i] != null && update[i].next[i].value == value) {
                    update[i].next[i] = update[i].next[i].next[i];
                }
            }
        }
    }

    private int randomLevel() {
        int level = 1;
        while (random.nextDouble() < PROBABILITY && level < MAX_LEVEL) {
            level++;
        }
        return level;
    }
}

从前序和中序遍历序列构建二叉树

class Solution {  
    private int[] preorder;  
    private int[] inorder;  
    private HashMap<Integer,Integer> idx_map;  
    private int pre_idx=0;  
  
    public TreeNode buildTree(int[] preorder, int[] inorder) {  
        this.preorder = preorder;  
        this.inorder = inorder;  
        idx_map = new HashMap<>();  
        int idx = 0;  
        for(Integer val : inorder){  
            idx_map.put(val,idx++);  
        }  
        return helper(0,inorder.length);  
    }  
  
    private TreeNode helper(int start,int end){  
        if(start==end){  
            return null;  
        }  
        int rootVal = preorder[pre_idx];  
        TreeNode root = new TreeNode(rootVal);  
        int index = idx_map.get(rootVal);  
        pre_idx++;  
        root.left = helper(start,index);  
        root.right = helper(index+1,end);  
        return root;  
    }  
}

从中序和后序遍历序列构建二叉树

class Solution {  
  
    private int[] inorder;  
    private int[] postorder;  
    private Map<Integer,Integer> map;  
    private int idx;  
  
    public TreeNode buildTree(int[] inorder, int[] postorder) {  
        this.inorder = inorder;  
        this.postorder = postorder;  
        this.map = new HashMap<>();  
        this.idx = inorder.length-1;  
        int idx_map = idx;  
        for(Integer val : inorder){  
            map.put(val,idx_map--);  
        }  
        return helper(0,idx+1);  
    }  
  
    private TreeNode helper(int start,int end){  
        if(start==end){  
            return null;  
        }  
        int rootVal = postorder[idx];  
        TreeNode root = new TreeNode(rootVal);  
        int index = map.get(rootVal);  
        idx--;  
        root.right = helper(start,index);  
        root.left = helper(index+1,end);  
        return root;  
    }  
}

字典树

class TrieNode {  
    // 存储节点的孩子节点  
    TrieNode[] children;  
    // 标记该节点是否为一个单词的结束  
    boolean isEndOfWord;  
  
    // 构造函数  
    public TrieNode() {  
        // 初始化孩子节点数组,大小为26,表示26个英文字母  
        children = new TrieNode[26];  
        isEndOfWord = false;  
    }  
}  
  
class Trie {  
    private TrieNode root;  
  
    // 构造函数  
    public Trie() {  
        root = new TrieNode();  
    }  
  
    // 插入一个单词到字典树中  
    public void insert(String word) {  
        TrieNode current = root;  
        // 遍历单词中的每一个字符  
        for (int i = 0; i < word.length(); i++) {  
            char ch = word.charAt(i);  
            int index = ch - 'a';  
            // 如果当前字符的节点不存在,创建一个新的节点  
            if (current.children[index] == null) {  
                current.children[index] = new TrieNode();  
            }  
            // 移动到下一个节点  
            current = current.children[index];  
        }  
        // 标记当前节点为一个单词的结束  
        current.isEndOfWord = true;  
    }  
  
    // 搜索一个单词是否在字典树中  
    public boolean search(String word) {  
        TrieNode current = root;  
        // 遍历单词中的每一个字符  
        for (int i = 0; i < word.length(); i++) {  
            char ch = word.charAt(i);  
            int index = ch - 'a';  
            // 如果当前字符的节点不存在,返回false  
            if (current.children[index] == null) {  
                return false;  
            }  
            // 移动到下一个节点  
            current = current.children[index];  
        }  
        // 检查最后一个节点是否标记为一个单词的结束  
        return current != null && current.isEndOfWord;  
    }  
  
    // 判断是否存在以给定前缀开头的单词  
    public boolean startsWith(String prefix) {  
        TrieNode current = root;  
        // 遍历前缀中的每一个字符  
        for (int i = 0; i < prefix.length(); i++) {  
            char ch = prefix.charAt(i);  
            int index = ch - 'a';  
            // 如果当前字符的节点不存在,返回false  
            if (current.children[index] == null) {  
                return false;  
            }  
            // 移动到下一个节点  
            current = current.children[index];  
        }  
        return true;  
    }  
}