3.17

集合、分治,树

LFU 缓存(hard)

thinking

缓存清除机制:LRU与LFU。LRU可以简单地通过哈希表+双向链表进行实现,LFU则要复杂的多,为双哈希+N个双向链表进行实现

解释好麻烦,不解释了,直接上代码。

solution

//codes from  leetcode
struct Node {
    int cnt, time, key, value;

    Node(int _cnt, int _time, int _key, int _value):cnt(_cnt), time(_time), key(_key), value(_value){}
    
    bool operator < (const Node& rhs) const {
        return cnt == rhs.cnt ? time < rhs.time : cnt < rhs.cnt;
    }
};
class LFUCache {
    // 缓存容量,时间戳
    int capacity, time;
    unordered_map<int, Node> key_table;
    set<Node> S;
public:
    LFUCache(int _capacity) {
        capacity = _capacity;
        time = 0;
        key_table.clear();
        S.clear();
    }
    
    int get(int key) {
        if (capacity == 0) return -1;
        auto it = key_table.find(key);
        // 如果哈希表中没有键 key,返回 -1
        if (it == key_table.end()) return -1;
        // 从哈希表中得到旧的缓存
        Node cache = it -> second;
        // 从平衡二叉树中删除旧的缓存
        S.erase(cache);
        // 将旧缓存更新
        cache.cnt += 1;
        cache.time = ++time;
        // 将新缓存重新放入哈希表和平衡二叉树中
        S.insert(cache);
        it -> second = cache;
        return cache.value;
    }
    
    void put(int key, int value) {
        if (capacity == 0) return;
        auto it = key_table.find(key);
        if (it == key_table.end()) {
            // 如果到达缓存容量上限
            if (key_table.size() == capacity) {
                // 从哈希表和平衡二叉树中删除最近最少使用的缓存
                key_table.erase(S.begin() -> key);
                S.erase(S.begin());
            }
            // 创建新的缓存
            Node cache = Node(1, ++time, key, value);
            // 将新缓存放入哈希表和平衡二叉树中
            key_table.insert(make_pair(key, cache));
            S.insert(cache);
        }
        else {
            // 这里和 get() 函数类似
            Node cache = it -> second;
            S.erase(cache);
            cache.cnt += 1;
            cache.time = ++time;
            cache.value = value;
            S.insert(cache);
            it -> second = cache;
        }
    }
};

词典中最长的单词

thinking

简单模拟即可,不过题目意思说的有点迷糊

solution

class Solution {
public:
    string longestWord(vector<string>& w) {
        sort(w.begin(),w.end());
        int n=w.size();
        unordered_set<string> hash;
        string ans="z";
        for(int i=0;i<n;++i) {
            if(w[i].size()==1) {
                hash.insert(w[i]);
                if(ans.size()==1&&ans>w[i])
                    ans=w[i];
            }
            else {
                int len=w[i].size();
                if(hash.count(w[i].substr(0,len-1))) {
                    hash.insert(w[i]);
                    if(len>ans.size()) ans=w[i];
                    else if(len==ans.size()&&ans>w[i]) ans=w[i];
                }
            }
        }
        return hash.empty()?"":ans;
    }
};

颠倒二进制位

thinking

简单模拟,倒叙遍历即可

solution

class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
      uint32_t ans=0;
      for(int i=0;i<32;++i) {
          ans|=(n&1)<<(31-i);
          n=n>>1;
        }
    return ans;
    }
};

有序链表转换二叉搜索树

thinking

可以参考一下下一题再做此题

solution

class Solution {
public:
    TreeNode* BSTbuild(int left,int right,vector<int>&nums) {
        int mid=left+(right-left)/2;
        TreeNode* node=new TreeNode(nums[mid]);
        if(left<mid) node->left=BSTbuild(left,mid-1,nums);
        if(mid<right) node->right=BSTbuild(mid+1,right,nums);
        return node;
    }
    TreeNode* sortedListToBST(ListNode* head) {
        vector<int> cnt;
        while(head) {
            cnt.push_back(head->val);
            head=head->next;
        }
        if(cnt.empty()) return nullptr;
        return BSTbuild(0,cnt.size()-1,cnt);
    }
};

将二叉搜索树变平衡

thinking

手撸AVL?不不不,我们将节点从树上取下,再重新构造二叉平衡树。

由贪心可以知道,我们每次对一半的数组进行构造左右子树,这样的树一定是最平衡的。证明略,参考

因此,我们每次将数组进行二分,递归地建立二叉平衡树。

solution

class Solution {
public:
    vector<int>cnt;
    void getnum(TreeNode* root) {
        if(root->left) getnum(root->left);
        cnt.push_back(root->val);
        if(root->right) getnum(root->right);
    }
    TreeNode* BSTbuild(int left,int right) {
        int mid=left+(right-left)/2;
        TreeNode* node=new TreeNode(cnt[mid]);
        if(left<mid) node->left=BSTbuild(left,mid-1);
        if(mid<right) node->right=BSTbuild(mid+1,right);
        return node;
    }
    TreeNode* balanceBST(TreeNode* root) {
        getnum(root);
        return BSTbuild(0,cnt.size()-1);
    }
};

将有序数组转换为二叉搜索树

thinking

与上一题同理,不再多说

solution

class Solution {
public:
    TreeNode* BSTbuild(int left,int right,vector<int>&nums) {
        int mid=left+(right-left)/2;
        TreeNode* node=new TreeNode(nums[mid]);
        if(left<mid) node->left=BSTbuild(left,mid-1,nums);
        if(mid<right) node->right=BSTbuild(mid+1,right,nums);
        return node;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return BSTbuild(0,nums.size()-1,nums);
    }
};
posted @ 2022-03-17 16:12  圣道  阅读(79)  评论(0)    收藏  举报