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题解)

posted @ 2022-02-14 01:18  SrtFrmGNU  阅读(31)  评论(0编辑  收藏  举报