Leetcode设计数据结构O(1)数据结构

目录

LRU:

LFU:

380. O(1) 时间插入、删除和获取随机元素

381. O(1) 时间插入、删除和获取随机元素 - 允许重复


LRU:

146. LRU 缓存机制

struct Node {
    Node *l, *r;
    int key, val;
    Node(int _key, int _val) :key(_key), val(_val) {}
}*head, *tail; //两个哨兵

class LRUCache {
public:
    int n;
    unordered_map<int, Node*> hash;

    //从双链表删除掉p节点
    void remove(Node* p) {
        p -> l -> r = p -> r;
        p -> r -> l = p -> l;
    }

    //在头部(head后)插入p节点
    void insert(Node* p) {
        p -> l = head;
        p -> r = head -> r;
        head -> r = p;
        p -> r -> l = p;
    }

    LRUCache(int capacity) {
        n = capacity;
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        head -> r = tail;
        tail -> l = head;
    }
    
    int get(int key) {
        if (!hash.count(key)) return -1;
        Node* p = hash[key];
        //使用过一次,把他插入到链表的头部
        remove(p);
        insert(p);
        return p -> val;
    }
    
    void put(int key, int value) {
        if (hash.count(key)) {
            hash[key] -> val = value;
            Node* p = hash[key];
            remove(p);
            insert(p);
        } else {
            if (hash.size() == n) {
                Node* p = tail -> l;
                remove(p);
                hash.erase(p -> key);
                delete p;
            }
            Node* q = new Node(key, value);
            hash[key] = q;
            insert(q);
        }
    }
};

LFU:

460. LFU 缓存

//双链表套双链表
//每一个block表示所有访问次数相同的点
//每一个blcok内有多个node,头结点是最近被访问的节点
class LFUCache {
	public : 
		struct Node {
			Node *left, *right;
			int key, val;
			Node(int _key, int _val) {
				this -> key = _key;
				this -> val = _val;
				left = right = NULL;
			}
		};

		struct Block {
			Block *left, *right;
			Node *head, *tail; //每个块内的头尾节点

			int cnt;//这个块内所有节点都是被访问了cnt次
			Block(int _cnt) {
				this -> cnt = _cnt;
				left = right = NULL;
				head = new Node(-1, -1), tail = new Node(-1, -1);//为了代码方便,维护两个哨兵
				head -> right = tail, tail -> left = head;
			}

			~Block() {
				delete head;
				delete tail;
			}

			void insert(Node *p) {
				//插入到块内的第一个节点
				p -> right = head -> right;
				head -> right -> left = p;
				head -> right = p;
				p -> left = head;
			}

			void remove(Node *p) {
				p -> left -> right = p -> right;
				p -> right -> left = p -> left;
			}

			bool empty() {
				return head -> right == tail;
			}
		}*head, *tail;// 维护两个哨兵

		int n;
		unordered_map<int, Block*> hash_block;
		unordered_map<int, Node*> hash_node;

		void insert(Block *p) {
			//在p的右侧插入一个新块,cnt为当前块的cnt+1
			auto cur = new Block(p -> cnt + 1);
			cur -> right = p -> right;
			p -> right -> left = cur;
			p -> right = cur;
			cur -> left = p;
		}

		void remove(Block* p) {
			p -> left -> right = p -> right;
			p -> right -> left = p -> left;
			delete p;
		}


		LFUCache(int capacity) {
			this -> n = capacity;
			head = new Block(0), tail = new Block(INT_MAX);
			head -> right = tail, tail -> left = head;
		}

		int get(int key) {
			if (hash_block.count(key) == 0) return -1;
			auto block = hash_block[key];
			auto node = hash_node[key];
			block -> remove(node);
			if (block -> right -> cnt != block -> cnt + 1) insert(block);
			block -> right -> insert(node);
			hash_block[key] = block -> right;
			if (block -> empty()) remove(block);
			return node -> val;
		}

		void put(int key, int value) {
			if (n == 0) return ;
			if (hash_block.count(key)) {
				hash_node[key] -> val = value;
				get(key);//更新一次cnt
			} else {
				if (hash_block.size() == n) {
					auto p = head -> right -> tail -> left;
					head -> right -> remove(p);
					if (head -> right -> empty()) remove(head -> right);
					hash_block.erase(p -> key);
					hash_node.erase(p -> key);
					delete p;
				}
				auto p = new Node(key, value);
				if (head -> right -> cnt != 1) insert(head);
				head -> right -> insert(p);
				hash_block[key] = head -> right;
				hash_node[key] = p;
			}
		}
};

380. O(1) 时间插入、删除和获取随机元素

class RandomizedSet {
public:
    /** Initialize your data structure here. */
    unordered_map<int, int> hash;
    vector<int> nums;

    RandomizedSet() {

    }

    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
    bool insert(int x) {
        if (hash.count(x) == 0) {
            nums.push_back(x);
            hash[x] = nums.size() - 1;
            return true;
        }
        return false;
    }

    /** Removes a value from the set. Returns true if the set contained the specified element. */
    bool remove(int x) {
        if (hash.count(x)) {
            int y = nums.back();
            int px = hash[x], py = hash[y];
            swap(nums[px], nums[py]);
            swap(hash[x], hash[y]);
            nums.pop_back();
            hash.erase(x);
            return true;
        }
        return false;
    }

    /** Get a random element from the set. */
    int getRandom() {
        return nums[rand() % nums.size()];
    }
};

381. O(1) 时间插入、删除和获取随机元素 - 允许重复

class RandomizedCollection {
public:
    unordered_map<int, unordered_set<int>> hash;
    vector<int> nums;

    /** Initialize your data structure here. */
    RandomizedCollection() {

    }

    /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
    bool insert(int x) {
        bool res = hash[x].empty();
        nums.push_back(x);
        hash[x].insert(nums.size() - 1);
        return res;
    }

    /** Removes a value from the collection. Returns true if the collection contained the specified element. */
    bool remove(int x) {
        if (hash[x].size()) {
            int px = *hash[x].begin(), py = nums.size() - 1;
            int y = nums.back();
            swap(nums[px], nums[py]);
            hash[x].erase(px), hash[x].insert(py);
            hash[y].erase(py), hash[y].insert(px);
            nums.pop_back();
            hash[x].erase(py);
            return true;
        }
        return false;
    }

    /** Get a random element from the collection. */
    int getRandom() {
        return nums[rand() % nums.size()];
    }
};

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值