基本题目

700. 二叉搜索树中的搜索

二叉搜索树的定义

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if (!root) return nullptr;
        else if (root->val > val) return searchBST(root->left, val);
        else if (root->val < val) return searchBST(root->right, val);
        else return root;
    }
};

98. 验证二叉搜索树

二叉搜索树的定义

class Solution {
public:
    bool check(TreeNode *root, int &min, int &max) {
        if (!root) return false;
        min = root->val;
        max = root->val;

        int minT, maxT;
        if (root->left) {
            if (!check(root->left, minT, maxT)) return false;
            if (maxT >= root->val) return false;
            min = minT;
        }
        if (root->right) {
            if (!check(root->right, minT, maxT)) return false;
            if (minT <= root->val) return false;
            max = maxT;
        }
        return true;
    }

    bool isValidBST(TreeNode* root) {
        int min, max;
        return check(root, min, max);
    }
};

递归过程的参数传递可以自底向上(引用/返回值),也可以自顶向下(参数)

二叉搜索树:仅需验证中序遍历结果的有序性即可

530. 二叉搜索树的最小绝对差

中序遍历的有序性

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        stack<TreeNode *> s;
        int prev = -1, diff = INT_MAX;
        TreeNode *tmp = root;

        while (!s.empty() || tmp) {
            while (tmp) {
                s.push(tmp);
                tmp = tmp->left;
            }
            tmp = s.top();
            s.pop();

            if (prev >= 0 && tmp->val - prev < diff)
                diff = tmp->val - prev;
            prev = tmp->val;

            tmp = tmp->right;
        }

        return diff;
    }
};

501. 二叉搜索树中的众数

中序遍历的有序性

class Solution {
public:
    vector<int> findMode(TreeNode* root) {
        vector<int> result;
        int occ = 0;
        stack<TreeNode *> s;
        TreeNode *tmp = root;
        int curr = INT_MIN, count = 0;
        bool flag = true;
        while (!s.empty() || tmp || flag) {
            while (tmp) {
                s.push(tmp);
                tmp = tmp->left;
            }

            if (s.empty()) {
                flag = false;
            }
            else {
                tmp = s.top();
                s.pop();
                if (tmp->val == curr) {
                    count++;
                    tmp = tmp->right;
                    continue;
                }
            }

            if (count > occ) {
                result.clear();
                result.push_back(curr);
                occ = count;
            }
            else if (count == occ) {
                result.push_back(curr);
            }

            if (tmp) {
                curr = tmp->val;
                count = 1;
                tmp = tmp->right;
            }
        }

        return result;
    }
};

236. 二叉树的最近公共祖先

记录父节点+链表相交

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        unordered_map<TreeNode *, TreeNode *> parent;
        parent[root] = nullptr;
        queue<TreeNode *> buffer;
        buffer.push(root);
        TreeNode *tmp, *tmp2;
        while (!buffer.empty()) {
            tmp = buffer.front();
            buffer.pop();
            if (tmp->left) {
                parent[tmp->left] = tmp;
                buffer.push(tmp->left);
            }
            if (tmp->right) {
                parent[tmp->right] = tmp;
                buffer.push(tmp->right);
            }
        }

        tmp = p;
        tmp2 = q;
        while (tmp != tmp2) {
            tmp = parent[tmp];
            tmp2 = parent[tmp2];
            if (!tmp) tmp = q;
            if (!tmp2) tmp2 = p;
        }
        return tmp;
    }
};

可以使用递归的方式求解:

  • 符合要求的节点中,左右子树都包含 p 或 q,或其本身等于 p 或 q 且一个子树包含 p 或 q
  • 利用返回值将两个节点向上传递,直到某个节点相遇(即 left, root, right 三者中包含 p 与 q),该节点即为所求
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // Both p, q in root, left, right: return root
        // Either p or q: return p/q
        // Nonzero value other than p or q: return left/right
        // All nullptr: return nullptr

        if (!root || root == p || root == q) return root;
        TreeNode *left = lowestCommonAncestor(root->left, p, q);
        TreeNode *right = lowestCommonAncestor(root->right, p, q);
        if (left && right) return root;
        return left ? left : right;
    }
};

235. 二叉搜索树的最近公共祖先

利用二叉搜索树的特性:公共祖先的值一定位于两节点值之间

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (p->val > q->val) swap(p, q);
        while (true) {
            if (root->val > q->val) root = root->left;
            else if (root->val < p->val) root = root->right;
            else break;
        }
        return root;
    }
};

701. 二叉搜索树中的插入操作

二叉搜索树的定义

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (!root) return new TreeNode(val);
        TreeNode *curr = root;
        while (true) {
            if (val < curr->val) {
                if (!curr->left) {
                    curr->left = new TreeNode(val);
                    return root;
                }
                else {
                    curr = curr->left;
                }
            }
            else {
                if (!curr->right) {
                    curr->right = new TreeNode(val);
                    return root;
                }
                else {
                    curr = curr->right;
                }
            }
        }
        return root;
    }
};

450. 删除二叉搜索树中的节点

分类讨论删除节点的位置

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        TreeNode *prev = nullptr, *curr = root;
        while (curr && curr->val != key) {
            prev = curr;
            if (curr->val > key) curr = curr->left;
            else curr = curr->right;
        }

        if (!curr) return root;
        if (!curr->left || !curr->right) {
            // Leaf node / one child
            if (prev) {
                if (curr->val > prev->val) prev->right = curr->left ? curr->left : curr->right;
                else prev->left = curr->left ? curr->left : curr->right;
                return root;
            }
            else {
                return curr->left ? curr->left : curr->right;
            }
        }

        // Two children: delete the greatest key in left subtree
        TreeNode *tmp = curr->left;
        while (tmp->right) tmp = tmp->right;
        curr->val = tmp->val;
        curr->left = deleteNode(curr->left, tmp->val);
        return root;
    }
};

669. 修剪二叉搜索树

递归。树结构的修改可以通过使用返回值赋值来实现

class Solution {
public:
    TreeNode *trimBST(TreeNode *node, int low, int high) {
        if (!node) return nullptr;
        if (node->val < low) return trimBST(node->right, low, high);
        else if (node->val > high) return trimBST(node->left, low, high);
        node->left = trimBST(node->left, low, high);
        node->right = trimBST(node->right, low, high);
        return node;
    }
};

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

二分递归

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums, int lo, int hi) {
        if (lo >= hi) return nullptr;
        int mi = (lo + hi) / 2;
        return new TreeNode(nums[mi], sortedArrayToBST(nums, lo, mi), sortedArrayToBST(nums, mi + 1, hi));
    }

    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return sortedArrayToBST(nums, 0, nums.size());
    }
};

538. 把二叉搜索树转换为累加树

中序遍历(反向)

class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        stack<TreeNode *> s;
        TreeNode *tmp = root;
        int sum = 0;
        while (!s.empty() || tmp) {
            while (tmp) {
                s.push(tmp);
                tmp = tmp->right;
            }
            tmp = s.top();
            s.pop();
            sum += tmp->val;
            tmp->val = sum;
            tmp = tmp->left;
        }
        return root;
    }
};