• LeetCode题解02(树、字典树、堆)


    目录

    LeetCode题解

    chap-4: 树

    1、验证二叉搜索树

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        bool isValidBST(TreeNode* root) {
            if(root == nullptr) return true;
            if(root->left == nullptr && root->right == nullptr) return true;
            auto left = root->left, right = root->right;
            while(left){
                if(left->val >= root->val) return false;
                left = left->right;
            }
            while(right){
                if(right->val <= root->val) return false;
                right = right->left;
            }
            return isValidBST(root->left) && isValidBST(root->right);
        }
    };
    

    2、恢复二叉搜索树

    思路:二叉搜索树满足中序遍历的有序性,可以通过查找中序遍历逆序对,进而确定交换值的位置

    class Solution {
    public:
        TreeNode *pre = NULL, *first = NULL, *second = NULL; 
        void recoverTree(TreeNode* root) {
            dfs(root);
            swap(first -> val, second -> val);
        }
        void dfs(TreeNode* root)
        {
            if (!root) return;
            dfs(root -> left);
            if (!pre) pre = root;
            if (root -> val < pre -> val)
            {
                if (!first) first = pre;
                second = root;
            }
            pre = root;
            dfs(root -> right);
        }
    };
    

    Morris遍历

    class Solution {
    public:
        void recoverTree(TreeNode* root) {
            TreeNode *first = NULL, *second, *prep = NULL;
            while (root)
            {
                if (!root->left)
                {
                    if (prep && prep->val > root->val)
                    {
                        if (!first) first = prep, second = root;
                        else second = root;
                    }
                    prep = root;
                    root = root->right;
                }
                else
                {
                    TreeNode *p = root->left;
                    while (p->right && p->right != root) p = p->right;
                    if (!p->right)
                    {
                        p->right = root;
                        root = root->left;
                    }
                    else
                    {
                        p->right = NULL;
                        if (prep && prep->val > root->val)
                        {
                            if (!first) first = prep, second = root;
                            else second = root;
                        }
                        prep = root;
                        root = root->right;
                    }
                }
            }
            swap(first->val, second->val);
        }
    };
    

    3、相同的树

    class Solution {
    public:
        bool isSameTree(TreeNode* p, TreeNode* q) {
            if(!p && !q) return true;
            if(!q || !p || p->val != q->val) return false;
            return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
        }
    };
    

    4、对称二叉树

    class Solution {
    public:
        bool dfs(TreeNode* r,TreeNode* l){
            if(!r && !l) return true;
            if(!r || !l || r->val != l->val) return false;
            return dfs(r->right,l->left) && dfs(r->left,l->right);
        }
        bool isSymmetric(TreeNode* root) {
            if(root == nullptr) return true;
            return dfs(root->right,root->left);
        }
    };
    

    5、二叉树的层序遍历

    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
            vector<vector<int>> ans;
            if(root == nullptr) return ans;
            queue<TreeNode*> q;
            q.push(root);
            while(q.size()){
                int n = q.size();
                vector<int> temp;
                while(n--){
                    auto t = q.front(); q.pop();
                    temp.push_back(t->val);
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
                ans.push_back(temp);
            }
            return ans;
        }
    };
    

    6、二叉树的层序遍历 II

    class Solution {
    public:
        vector<vector<int>> levelOrderBottom(TreeNode* root) {
            vector<vector<int>> res;
            queue<TreeNode*> q;
            if (root) q.push(root);
            while (q.size()) {
                vector<int> level;
                int len = q.size();
                while (len -- ) {
                    auto t = q.front();
                    q.pop();
                    level.push_back(t->val);
                    if (t->left) q.push(t->left);
                    if (t->right) q.push(t->right);
                }
                res.push_back(level);
            }
            reverse(res.begin(),res.end());
            return res;
        }
    };
    

    7、二叉树的锯齿形层序遍历

    class Solution {
    public:
        vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
            vector<vector<int>> ans; if(root == nullptr) return ans;
            queue<TreeNode*> q;
            q.push(root); bool zig = false;
            while(q.size()){
                int n = q.size(); vector<int> temp;
                while(n--){
                    auto t = q.front(); q.pop();
                    temp.push_back(t->val);
                    if(t->left)q.push(t->left);
                    if(t->right)q.push(t->right);
                }
                if(zig) reverse(temp.begin(),temp.end());
                zig = !zig;
                ans.push_back(temp);
            }
            return ans;
        }
    };
    

    8、二叉树的最大深度

    class Solution {
    public:
        int maxDepth(TreeNode* root) {
            if(root == nullptr) return 0;
            return max(maxDepth(root->left),maxDepth(root->right)) + 1;
        }
    };
    

    9、从前序与中序遍历序列构造二叉树

    class Solution {
    public:
        unordered_map<int,int> pos;
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
            int n = preorder.size();
            for (int i = 0; i < n; i ++ )
                pos[inorder[i]] = i;
            return dfs(preorder, inorder, 0, n - 1, 0, n - 1);
        }
        TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir)
        {
            if (pl > pr) return NULL;
            int k = pos[pre[pl]] - il;
            TreeNode* root = new TreeNode(pre[pl]);
            root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);
            root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);
            return root;
        }
    };
    

    10、从中序与后序遍历序列构造二叉树

    class Solution {
    public:
        TreeNode* buildTree(vector<int> in, vector<int> post) {
            if(in.size() == 0) return nullptr;
            auto root = new TreeNode(post.back());
            int i = 0; while(i<in.size() && in[i] != post.back()) i++;  
            root->left = buildTree(vector<int>(in.begin(),in.begin()+i),vector<int>(post.begin(),post.begin()+i));
            root->right = buildTree(vector<int>(in.begin()+i+1,in.end()),vector<int>(post.begin()+i,post.end()-1));
            return root;
        }
    };
    

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

    class Solution {
    public:
        TreeNode* sortedArrayToBST(vector<int> nums) {
            if(nums.empty()) return nullptr;
            int n = nums.size(), mid = n>>1;
            auto root = new TreeNode(nums[mid]);
            root->left = sortedArrayToBST(vector<int>(nums.begin(),nums.begin()+mid));
            root->right = sortedArrayToBST(vector<int>(nums.begin()+mid+1,nums.end()));
            return root;
        }
    };
    

    12、有序链表转换二叉搜索树

    class Solution {
    public:
        TreeNode* sortedListToBST(ListNode* head) {
            if(head == nullptr) return nullptr;
            auto dummy = new ListNode(-1);
            dummy->next = head;
            auto slow = dummy, fast = dummy;
            while(slow && fast){
                slow = slow->next;
                if(fast->next) fast = fast->next->next;
                else fast = fast->next;
            }
            fast = dummy;
            while(fast->next != slow) fast = fast->next;
            auto root = new TreeNode(slow->val);
            fast->next = nullptr;
            root->left = sortedListToBST(dummy->next);
            root->right = sortedListToBST(slow->next);
            return root;
        }
    };
    

    13、平衡二叉树

    class Solution {
    public:
        int maxdepth(TreeNode* root){
            if(root == nullptr) return 0;
            return max(maxdepth(root->left),maxdepth(root->right)) + 1;
        }
        bool isBalanced(TreeNode* root) {
            if(root == nullptr) return true;
            if(abs(maxdepth(root->left) - maxdepth(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right))
                return true;
            else return false;
        }
    };
    

    14、二叉树的最小深度

    class Solution {
    public:
        int minDepth(TreeNode* root) {
            if(root == nullptr) return 0;
            if(root->left == nullptr && root->right == nullptr) return 1;
            int l = INT_MAX, r = INT_MAX;
            if(root->left) l = min(minDepth(root->left),l);
            if(root->right) r = min(minDepth(root->right),r);
            return min(l,r)+1;
        }
    };
    

    15、路径总和

    class Solution {
    public:
        bool hasPathSum(TreeNode* root, int targetSum) {
            if(root == nullptr) return false;
            if(root->left == nullptr && root->right == nullptr && targetSum == root->val) return true;
            return hasPathSum(root->left,targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
        }
    };
    

    16、路径总和 II

    class Solution {
    public:
        vector<int> path;
        vector<vector<int>> ans;
        void dfs(TreeNode* root, int targetSum){
            if(root == nullptr) return;
            if(root->left == nullptr && root->right == nullptr && root->val == targetSum) {
                path.push_back(root->val); 
                ans.push_back(path);
                path.pop_back(); 
                return;
            }
            path.push_back(root->val);
            dfs(root->left,targetSum - root->val);
            dfs(root->right,targetSum - root->val);
            path.pop_back();
        }
    
        vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
            dfs(root,targetSum);
            return ans;
        }
    };
    

    17、二叉树展开为链表

    class Solution {
    public:
        void flatten(TreeNode* root) {
            if(root == nullptr) return;
            stack<TreeNode*>s;
            s.push(root); auto temp = new TreeNode(-1);        
            while(s.size()){
                auto t = s.top(); s.pop();
                if(t->right) s.push(t->right);
                if(t->left) s.push(t->left);
                temp->left = nullptr;
                temp->right = t; temp = temp->right;
            }     
            root = temp->right;   
        }
    };
    // O(1)空间负责度
    class Solution {
    public:
        void flatten(TreeNode* root) {
            TreeNode *now = root;
            while (now)
            {
                if (now->left)
                {
                    TreeNode *p = now->left;
                    while (p->right) p = p->right;
                    p->right = now->right;
                    now->right = now->left;
                    now->left = 0;
                }
                now = now->right;
            }
        }
    };
    

    18、填充每个节点的下一个右侧节点指针【×】

    class Solution {
    public:
        Node* connect(Node* root) {
            if(root == NULL) return root;
            auto l = connect(root->left);
            auto r = connect(root->right);
            while(l && r){
                l->next = r;
                l = l->right; r = r->left;
            }
            return root;
        }
    };
    // 进阶
    class Solution {
    public:
        Node* connect(Node* root) {
            if (!root) return root;
            auto source = root;
            while (root->left) {
                for (auto p = root; p; p = p->next) {
                    p->left->next = p->right;
                    if (p->next) p->right->next = p->next->left;
                }
                root = root->left;
            }
            return source;
        }
    };
    

    19、填充每个节点的下一个右侧节点指针 II 【×】

    class Solution {
    public:
        Node* connect(Node* root) {
            if(!root) return root;
            auto cur = root;
            while(cur){
                auto head = new Node(-1), tail = head;
                for(auto p =cur;p;p=p->next){
                    if(p->left) tail = tail->next = p->left;
                    if(p->right) tail = tail->next = p->right;
                }
                cur = head->next;
            }
            return root;
        }
    };
    

    20、二叉树中的最大路径和【×】

    class Solution {
    public:
        int ans = INT_MIN;
        int dfs(TreeNode* root){
            if(!root) return 0;
            int l = max(0,dfs(root->left));
            int r = max(0,dfs(root->right));
            ans = max(ans,root->val + l + r);
            return root->val + max(l,r);
        }
        int maxPathSum(TreeNode* root) {     
            dfs(root);
            return ans;
        }
    };
    

    21、求根节点到叶节点数字之和

    class Solution {
    public:
        int ans = 0;
        int sumNumbers(TreeNode* root) {
            if(root)dfs(root, 0);
            return ans;
        }
        void dfs(TreeNode* root, int number)
        {
            number = number * 10 + root->val;
            if(!root -> left && !root->right) ans += number;
            if(root->left) dfs(root->left,number); 
            if(root->right) dfs(root->right, number);
        }
    };
    

    22、二叉树的前序遍历

    class Solution {
    public:
        vector<int> preorderTraversal(TreeNode* root) {
            vector<int> ans; if(root==nullptr) return ans;
            stack<TreeNode*> s;
            s.push(root);
            while(s.size()){
                auto t = s.top(); s.pop();
                ans.push_back(t->val);
                if(t->right) s.push(t->right);
                if(t->left) s.push(t->left);
            }
            return ans;
        }
    };
    

    23、二叉树的后序遍历【×】

    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* root) {
            vector<int> ans; if(!root) return ans;
            stack<TreeNode*> s;
            s.push(root);
            while(s.size()){
                root = s.top();s.pop();
                ans.push_back(root->val);
                if(root->left) s.push(root->left);
                if(root->right) s.push(root->right);
            }
            reverse(ans.begin(),ans.end());
            return ans;
        }
    };
    
    // 不取巧
    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* cur) {
            stack<TreeNode*> s;
            vector<int> ans;
            TreeNode* last = nullptr; // 开辟变量存储前一次访问位置
            while(cur != nullptr || s.size()){
                while(cur != nullptr){
                    s.push(cur);
                    cur = cur->left;
                }
                cur = s.top();
                if(cur->right == nullptr || cur->right == last){
                    ans.push_back(cur->val);
                    last = cur;
                    cur = nullptr;
                    s.pop();
                }else cur = cur->right;
            }
            return ans;
        }
    };
    

    24、二叉搜索树迭代器

    class BSTIterator {
    public:
        stack<TreeNode*> s;
        BSTIterator(TreeNode* root) {
            while(root){
                s.push(root);
                root = root->left;
            }
        }    
        int next() {
            auto cur = s.top();
            s.pop();
            int v = cur->val;
            cur = cur->right;
            while(cur){s.push(cur); cur = cur->left;}
            return v;
        }    
        bool hasNext() {
            return !s.empty();
        }
    };
    

    25、完全二叉树的节点个数

    1、对于每个节点,计算一直向左和一直向右的高度,如果相等则说明是满二叉树,那么该树节点个数为\(2^h−1\)

    2、如果不相等则说明不是满二叉树,则需要递归地向下求解,该棵树的节点个数等于1+左子树节点数+右子树节点数

    满完全二叉节点总数

    class Solution {
    public:
        int countNodes(TreeNode* root) {
            if(!root) return 0;
            auto l = root, r = root;
            int a = 0, b = 0;
            while(l){a++; l = l->left;}
            while(r){b++; r = r->right;}
            if(a == b) return (1<<a) - 1;
            return countNodes(root->left) + countNodes(root->right) + 1;
        }
    };
    

    26、翻转二叉树

    class Solution {
    public:
        TreeNode* invertTree(TreeNode* root) {
            if(root == nullptr) return root;
            swap(root->left, root->right);
            invertTree(root->left);
            invertTree(root->right);
            return root;
        }
    };
    

    27、二叉搜索树中第K小的元素

    class Solution {
    public:
        int dfs(TreeNode* root){
            if(!root) return 0;
            return dfs(root->left) + dfs(root->right) + 1;
        }
        int kthSmallest(TreeNode* root, int k) {
            int m = dfs(root->left);
            if(m+1 == k) return root->val;
            else if(m > k) return kthSmallest(root->left,k);
            else if(m == k){
                root = root->left;
                while(root->right) root = root->right;
                return root->val;
            }else return kthSmallest(root->right,k-m-1);
        }
    };
    

    28、二叉树的序列化与反序列化【×】

    class Codec {
    public:
        void dfs(TreeNode* root,string &help){
            if(!root) help += "#,";
            else{
                help += to_string(root->val) + ',';
                dfs(root->left,help);
                dfs(root->right,help);
            }
        }
        // Encodes a tree to a single string.
        string serialize(TreeNode* root) {
            string help;
            dfs(root,help);
            return help;
        }
        TreeNode* vdfs(const string& data,int& i){ // 引用减少内存重复申请 + 
            if(i>=data.size()) return NULL;
            int k = i;
            while(i<data.size() && data[i] != ',')i++;
            string s = data.substr(k,i++ - k);
            if(s == "#") return NULL;
            else{
                auto t = new TreeNode(stoi(s));
                t->left = vdfs(data,i);
                t->right = vdfs(data,i);
                return t;
            }        
        }
        // Decodes your encoded data to tree.
        TreeNode* deserialize(string data) {
            int i = 0;
            return vdfs(data,i);
        }
    };
    

    29、将数据流变为多个不相交区间

    #define x first
    #define y second
    typedef pair<int, int> PLL;
    
    class SummaryRanges {
    public:
        /** Initialize your data structure here. */
        set<PLL> S;
    
        SummaryRanges() {
            S.insert({INT_MIN, INT_MIN}), S.insert({INT_MAX, INT_MAX});
        }
    
        void addNum(int num) {
            auto r = S.upper_bound({num, INT_MAX});
            auto l = r; -- l;
            if (l->y >= num) return;
            if (l->y == num - 1 && r->x == num + 1) {
                S.insert({l->x, r->y});
                S.erase(l), S.erase(r);
            } else if (l->y == num - 1) {
                S.insert({l->x, num});
                S.erase(l);
            } else if (r->x == num + 1) {
                S.insert({num, r->y});
                S.erase(r);
            } else {
                S.insert({num, num});
            }
        }
    
        vector<vector<int>> getIntervals() {
            vector<vector<int>> res;
            for (auto& p: S)
                if (p.x != INT_MIN && p.x != INT_MAX)
                    res.push_back({(int)p.x, (int)p.y});
            return res;
        }
    };
    

    30、左叶子之和

    class Solution {
    public:
        void dfs(TreeNode* root,TreeNode* pre,int& ans){
            if(root == nullptr) return;
            if(!root->left && !root->right && root == pre->left) ans+=root->val;
            else dfs(root->left,root,ans), dfs(root->right,root,ans);
    
        }
        int sumOfLeftLeaves(TreeNode* root) {
            int ans = 0;
            dfs(root,root,ans);
            return ans;
        }
    };
    

    31、N 叉树的层序遍历

    class Solution {
    public:
        vector<vector<int>> levelOrder(Node* root) {
            vector<vector<int>> ans;
            if(!root) return ans;
            queue<Node*> q;
            q.push(root);
            while(q.size()){
                int n = q.size(); vector<int> temp;
                while(n--){
                    auto t = q.front();q.pop();
                    for(auto& a:t->children){
                        q.push(a);
                    }
                    temp.push_back(t->val);
                }    
                ans.push_back(temp);
            }
            return ans;
        }
    };
    

    32、序列化和反序列化二叉搜索树

    class Codec {
    public:
        void dfs(TreeNode* root,string &ans){
            if(root == NULL) return;
            ans += to_string(root->val) + ' ';
            dfs(root->left,ans), dfs(root->right,ans);
        }
        // Encodes a tree to a single string.
        string serialize(TreeNode* root) {
            string ans;
            dfs(root,ans);
            return ans;
        }
        TreeNode* vdfs(vector<int>& data,int& u,int Max,int Min){
            if(u == data.size() || data[u] > Max || data[u] < Min) return NULL;
            auto root = new TreeNode(data[u++]);
            root->left = vdfs(data,u,root->val,Min);
            root->right = vdfs(data,u,Max,root->val);
            return root;
        }
    
        // Decodes your encoded data to tree.
        TreeNode* deserialize(string data) {
            vector<int> d;
            stringstream sin(data);
            int n=0, u=0;
            while(sin>>n) d.push_back(n);
            return vdfs(d,u,INT_MAX,INT_MIN);
        }
    };
    

    33、删除二叉搜索树中的节点

    class Solution {
    public:
        void dfs(TreeNode*& root, int k){
            if(!root) return;
            if(root->val == k){
                if(!root->left && !root->right) root=nullptr;
                else if (!root->left) root = root->right;  // 只有右儿子
                else if (!root->right) root = root->left;  // 只有左儿子
                else {
                    auto  t = root->left;
                    while(t->right) t = t->right;
                    root->val = t->val;
                    dfs(root->left,t->val);
                }
            }else if(root->val < k) dfs(root->right,k);
            else dfs(root->left,k);
        }
        TreeNode* deleteNode(TreeNode* root, int key) {
            dfs(root,key);
            return root;
        }
    };
    

    34、二叉搜索树中的众数【×】

    class Solution {
    public:
        vector<int> ans;
        int maxc = 0, curc = 0, last;    
        void dfs(TreeNode*root){
            if(root == nullptr) return;
            dfs(root->left);
            if (!curc || root->val == last) {
                curc ++;
                last = root->val;
            } else {
                last = root->val;
                curc = 1;
            }
            if (curc > maxc) ans = {last}, maxc = curc;
            else if (curc == maxc) ans.push_back(last);
            dfs(root->right);
        }
        vector<int> findMode(TreeNode* root) {
            dfs(root);
            return ans;
        }
    };
    

    35、找树左下角的值

    // bfs
    class Solution {
    public:
        int findBottomLeftValue(TreeNode* root) {
            int ans;
            queue<TreeNode*> q;
            q.push(root);
            while(q.size()){
                auto t = q.front(); ans = t->val;
                int n = q.size();
                while(n--){
                    t = q.front(); q.pop();
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
            }
            return ans;
        }
    };
    
    // dfs
    class Solution {
    public:
        int maxd = 0,ans = 0;
        int findBottomLeftValue(TreeNode* root) {
            dfs(root,1);
            return ans;
        }
        void dfs(TreeNode*root,int d){
            if(!root) return;
            if(d > maxd){
                maxd = d;
                ans = root->val;
            }dfs(root->left,d+1), dfs(root->right,d+1);
        }
    };
    

    36、在每个树行中找最大值

    class Solution {
    public:
        unordered_map<int, int> hash;
        int maxd = 0;
    
        vector<int> largestValues(TreeNode* root) {
            dfs(root, 1);
            vector<int> res;
            for (int i = 1; i <= maxd; i ++ )
                res.push_back(hash[i]);
            return res;
        }
    
        void dfs(TreeNode* root, int d) {
            if (!root) return;
            maxd = max(maxd, d);
            if (hash.count(d) == 0) hash[d] = root->val;
            else hash[d] = max(hash[d], root->val);
            dfs(root->left, d + 1);
            dfs(root->right, d + 1);
        }
    };
    

    37、奇偶树

    class Solution {
    public:
        bool isEvenOddTree(TreeNode* root) {
            queue<TreeNode*> q;
            if (root) q.push(root);
            int level = 0;
            while (!q.empty()) {            
                int len = q.size();
                int value = (level == 0) ? INT_MIN : INT_MAX;
                while (len--) {
                    auto cur = q.front(); q.pop();
                    if ((level == 0) && (cur->val % 2 == 0 || cur->val <= value) ||
                        (level == 1) && (cur->val % 2 == 1 || cur->val >= value))
                        return false;
                    value = cur->val;
                    if (cur->left)  q.push(cur->left);
                    if (cur->right)  q.push(cur->right);
                }
                level ^= 1;
            }
            return true;
        }
    };
    

    [Go Back~~](# LeetCode题解)

    chap-5: Trie树(字典树)

    1、实现 Trie (前缀树)

    class Trie {
    public:
        struct Node{
            Node * nxt[26];
            bool end;
            Node(){
                for(int i=0;i<26;i++) nxt[i] = NULL;
                end = false;
            }
        };
        Node* data;
        /** Initialize your data structure here. */
        Trie() {
            data = new Node();
        }
        
        /** Inserts a word into the trie. */
        void insert(string word) {
            auto t = data;
            for(auto& c:word){
                if(t->nxt[c-'a'] == NULL)
                    t->nxt[c-'a'] = new Node();            
                t = t->nxt[c - 'a'];
            }
            t->end = true;
        }
        
        /** Returns if the word is in the trie. */
        bool search(string word) {
            auto t = data;
            for(auto& c:word){
                if(t->nxt[c-'a'])
                    t = t->nxt[c - 'a'];
                else return false;
            }
            return t->end == true;
        }
        
        /** Returns if there is any word in the trie that starts with the given prefix. */
        bool startsWith(string prefix) {
            auto t = data;
            for(auto& c:prefix){
                if(t->nxt[c-'a'])
                    t = t->nxt[c - 'a'];
                else return false;
            }
            return true;
        }
    };
    

    2、添加与搜索单词 - 数据结构设计

    class WordDictionary {
    public:
        struct Node{
            Node* nxt[26];
            bool end;
            Node(){
                for(int i = 0;i<26;i++) nxt[i] = NULL;
                end = false;
            }
        }*root;
        /** Initialize your data structure here. */
        WordDictionary() {
            root = new Node();
        }
        
        void addWord(string word) {
            auto t = root;
            for(auto &c:word){
                if(t->nxt[c - 'a'] == NULL)
                    t->nxt[c-'a'] = new Node();
                t = t->nxt[c - 'a'];
            }
            t->end = true;
        }
        
        bool dfs(Node* t,string& word,int u){
            if(!t || u == word.size()) return false;        
            if(word[u] != '.'){
                if(t->nxt[word[u] - 'a'] == NULL) return false;
                else if(u == word.size() - 1) return t->nxt[word[u] - 'a']->end == true;
                else return dfs(t->nxt[word[u] - 'a'],word,u+1);
            }else{
                auto f = false;
                for(auto i = 0;i<26;i++){
                    if(t->nxt[i]) 
                        if(u == word.size() -1 && t->nxt[i]->end)  return true;
                        else f |= dfs(t->nxt[i],word,u+1);
                }
                return f;
            }
        }
    
        bool search(string word) {
            auto t = root;
            return dfs(t,word,0);
        }
    };
    

    3、单词搜索 II

    // board建立trie树
    class Solution {
    public:
        struct Node{
            Node* nxt[26];
            Node(){
                for(auto i = 0;i<26;i++) nxt[i] = NULL;
            }
        }*root;
        int col[4] = {1,0,-1,0}, row[4] = {0,1,0,-1};
        vector<vector<bool>> f;
        void dfs(Node* t,vector<vector<char>>& board, int i,int j,int u,int cnt){
            if(u == cnt) return;
            for(int k = 0;k<4;k++){
                int x = i+row[k], y = j+col[k];
                if(x>=0 && x<board.size() && y>=0 && y<board[0].size() && !f[x][y]){
                    auto temp = t;
                    if(t->nxt[board[x][y] -'a'] == NULL) t->nxt[board[x][y] -'a'] = new Node;
                    temp = t->nxt[board[x][y] -'a'];
                    f[x][y] = true;
                    dfs(temp,board,x,y,u+1,cnt);
                    f[x][y] = false;
                }
            }
        }
    
        bool search(Node* t,string& word){
            for(auto &c:word){
                if(t->nxt[c - 'a'] == NULL) return false;
                else t = t->nxt[c - 'a'];
            }
            return true;
        }
    
        vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
            root = new Node();
            f = vector<vector<bool>>(board.size(),vector<bool>(board[0].size(),false));
            int cnt = 0; vector<string> ans;
            for(auto &word:words) cnt = max(cnt,(int)word.size());
            for(int i = 0;i<board.size();i++){
                for(int j = 0;j<board[0].size();j++){
                    auto t = root;
                    if(t->nxt[board[i][j] -'a'] == NULL) t->nxt[board[i][j] -'a'] = new Node;
                    t = t->nxt[board[i][j] -'a'];
                    f[i][j] = true;
                    dfs(t,board,i,j,1,cnt);
                    f[i][j] = false;
                }
            }
            for(auto &word:words){
                auto t = root;
                if(word.size() <= board.size()*board[0].size() && search(t,word)) ans.push_back(word);
            }
            return ans;
        }
    };
    
    // words建trie树
    class Solution {
    public:
        struct Node {
            int id;
            Node *son[26];
            Node() {
                id = -1;
                for (int i = 0; i < 26; i ++ ) son[i] = NULL;
            }
        }*root;
        unordered_set<int> ids;
        vector<vector<char>> g;
        int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
    
        void insert(string& word, int id) {
            auto p = root;
            for (auto c: word) {
                int u = c - 'a';
                if (!p->son[u]) p->son[u] = new Node();
                p = p->son[u];
            }
            p->id = id;
        }
    
        vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
            g = board;
            root = new Node();
            for (int i = 0; i < words.size(); i ++ ) insert(words[i], i);
    
            for (int i = 0; i < g.size(); i ++ )
                for (int j = 0; j < g[i].size(); j ++ ) {
                    int u = g[i][j] - 'a';
                    if (root->son[u])
                        dfs(i, j, root->son[u]);
                }
    
            vector<string> res;
            for (auto id: ids) res.push_back(words[id]);
            return res;
        }
    
        void dfs(int x, int y, Node* p) {
            if (p->id != -1) ids.insert(p->id);
            char t = g[x][y];
            g[x][y] = '.';
            for (int i = 0; i < 4; i ++ ) {
                int a = x + dx[i], b = y + dy[i];
                if (a >= 0 && a < g.size() && b >= 0 && b < g[0].size() && g[a][b] != '.') {
                    int u = g[a][b] - 'a';
                    if (p->son[u]) dfs(a, b, p->son[u]);
                }
            }
            g[x][y] = t;
        }
    };
    

    4、数组中两个数的最大异或值

    class Solution {
    public:
        struct Node{
            Node* nxt[2];
            Node(){
                nxt[0] = NULL;
                nxt[1] = NULL;
            }
        };
        int findMaximumXOR(vector<int>& nums) {
            int ans = 0; if(nums.size() == 1) return ans;
            auto root = new Node();        
            for(auto&num:nums) {
                auto t = root;
                bitset<32> n = num;
                for(int i = 31;~i;i--){
                    if(t->nxt[n[i]] == NULL) t->nxt[n[i]] = new Node;
                    t = t->nxt[n[i]];
                }
            }
            for(auto&num:nums) {
                auto t = root;
                bitset<32> n = num;
                int b = 0;
                for(int i = 31;~i;i--){
                    if(t->nxt[~n[i]]){
                        b = (b<<1) + ~n[i];
                        t = t->nxt[~n[i]];
                    }else {
                        b = (b<<1) + n[i];
                        t = t->nxt[n[i]];
                    }
                }
                ans = max(ans,num^b);
            }
            return ans;
        }
    };
    

    [Go Back~~](# LeetCode题解)

    chap-6: 堆

    1、数组中的第K个最大元素

    // 堆
    class Solution {
    public:
        vector<int> tree;
        void adjust(int root,int k){
            auto t = tree[root], j = 2*root+1;
            while(j<k){
                if(j+1<k && tree[j+1] < tree[j]) j++;
                if(tree[j] > t) break;
                tree[(j-1)/2] = tree[j];
                j = 2*j+1; 
            }
            tree[(j-1)/2] = t;
        }
        int findKthLargest(vector<int>& nums, int k) {
            int n = nums.size(), i = 0;
            tree = vector<int>(k);
            for(i = 0;i<k;i++) tree[i] = nums[i];
            for(i = k/2;~i;i--) adjust(i,k);
            for(i = k;i<n;i++){
                if(nums[i] > tree[0]) tree[0] = nums[i], adjust(0,k);
            }
            return tree[0];
        }
    };
    // api-优先队列
    class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            priority_queue<int,vector<int>,greater<int>> help;
            for(auto &num:nums){
                help.push(num);
                if(help.size() > k) help.pop();
            }
            return help.top();
        }
    };
    
    // 快排
    class Solution {
    public:
        int quick_sort(vector<int>& nums,int x,int y,int k){        
            if(x == y) return nums[k];
            int l = x-1, r = y+1;
            auto q = nums[x];
            while(l < r){
                do l++; while(nums[l] > q);
                do r--; while(nums[r] < q);
                if(l<r) swap(nums[l],nums[r]);
            }
            if(k <= r) return quick_sort(nums,x,r,k);
            else return quick_sort(nums,r+1,y,k);
        }
    
        int findKthLargest(vector<int>& nums, int k) {
            return quick_sort(nums,0,nums.size()-1,k-1);
        }
    };
    // 库函数
    class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            nth_element(nums.begin(),nums.begin()+((int)nums.size() - k),nums.end());
            return nums[(int)nums.size() - k];
        }
    };
    

    2、数据流的中位数【对顶堆】

    // 如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法? [计数排序,vector<int>(100)]
    // 如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法? [计数排序,增开[-INT_max,0)与(101,INT_max]]
    class MedianFinder {
    public:
        /** initialize your data structure here. */
        priority_queue<int> big;
        priority_queue<int,vector<int>,greater<int>> small;
        MedianFinder() {
    
        }    
        void addNum(int num) {
            if(big.empty() || num <= big.top())
                big.push(num);
            else small.push(num);
    
            if(big.size() == small.size() + 2){
                auto t = big.top(); big.pop();
                small.push(t);
            }else if(small.size() == big.size()+1){
                auto t = small.top(); small.pop();
                big.push(t);
            }
        }    
        double findMedian() {
            if(big.size() == small.size()) return (big.top()+small.top())/2.0;
            else return big.top();
        }
    };
    

    3、滑动窗口中位数 【对顶堆】

    class Solution {
    public:
        multiset<int> left,right;
        int k;
        double find_m(){
            if(k%2) return *right.begin();
            else return ((double)*left.rbegin() + *right.begin())/2;
        }
        vector<double> medianSlidingWindow(vector<int>& nums, int k_) {
            k = k_;
            vector<double> ans;
            for(int i = 0;i<k;i++) right.insert(nums[i]);
            for(int i = 0;i<k/2;i++) {
                auto t = *right.begin();
                left.insert(t);
                right.erase(right.find(t));
            }
            ans.push_back(find_m());
            for(int i=k;i<nums.size();i++){
                auto a = nums[i], b = nums[i-k];
                if(a >= *right.begin()) right.insert(a);
                else left.insert(a);
    
                if(right.find(b) != right.end()){
                    right.erase(right.find(b));
                }else left.erase(left.find(b));
    
                while(right.size() > left.size() + 1){ // 此处有别于第二题
                    a = *right.begin();
                    right.erase(right.find(a));
                    left.insert(a);
                }
                while(left.size() > right.size()){ // 此处有别于第二题
                    a = *left.rbegin();
                    left.erase(left.find(a));
                    right.insert(a);
                }
                ans.push_back(find_m());
            }
    
            return ans;
        }
    };
    

    4、前 K 个高频元素

    class Solution {
    public:
        static bool mycmp(const pair<int,int> &a,const pair<int,int> & b) {
            return a.second > b.second;
        }
        vector<int> topKFrequent(vector<int>& nums, int k) {
            unordered_map<int,int> m;        
            for(auto &num:nums) m[num]++;
            vector<pair<int,int>> t(m.begin(),m.end());
            sort(t.begin(),t.end(),mycmp);
            vector<int> ans;
            while(k--){
                ans.push_back(t[k].first);
            }
            return ans;
        }
    };
    

    5、查找和最小的K对数字【多路归并】

    class Solution {
    public:
        typedef pair<int,int> pii;
        vector<vector<int>> kSmallestPairs(vector<int>& a, vector<int>& b, int k) {
            vector<vector<int>> ans;
            priority_queue<pii,vector<pii>,greater<pii>> help;
            for(int j=0;j<b.size();j++) help.push(make_pair(a[0]+b[j],0));
            while(k-- && help.size()){
                auto t = help.top(); help.pop();
                ans.push_back({a[t.second],t.first - a[t.second]});
                if(t.second+1 < a.size())
                    help.push(make_pair(t.first - a[t.second] + a[t.second+1],t.second+1));
            }
            return ans;
        }
    };
    

    6、根据字符出现频率排序【topK】

    class Solution {
    public:
        typedef pair<int,char> pic;
        string frequencySort(string s) {
            unordered_map<char,int> hash;
            for(auto c:s) hash[c]++;
            priority_queue<pic> t;
            for(auto &c:hash){
                t.push(make_pair(c.second,c.first));
            }
            string ans;
            while(t.size()){
                auto c = t.top();
                while(c.first--)
                    ans += c.second;
                t.pop();
            }
            return ans;
        }
    };
    

    [Go Back~~](# LeetCode题解)

  • 相关阅读:
    System.TypeInitializationException 类型初始值设定项引发异常
    asp.net webapi下json传值方式
    The remote name could not be resolved: 'nuget.org'(未能解析此远程名称:’nuget.org’)
    关于集成Paypal Express Checkout支付功能
    Syntax error at line 16 while loading: expected ')', got keyword 'in' or(i.isArray(t)||(t in e?t=[t]:(t=i.came
    如何在MVC3 razor视图下的ViewsStart文件中设置使用两套不同的Layout布局视图
    knockout使用技巧:告知knockout忽略页面容器内特定部分的绑定
    LINQ to Entities已知问题及注意事项
    jQuery中.live()方法的使用方法
    Uncaught TypeErroe: Uncaught TypeError: Cannot call method 'push' of undefined 和 Uncaught TypeError: undefined is not a function
  • 原文地址:https://www.cnblogs.com/SrtFrmGNU/p/15891047.html
Copyright © 2020-2023  润新知