1、修剪二叉查找树

669. Trim a Binary Search Tree(Easy)
给定一个二叉树,和一个范围 [L, R] (R >= L),只保留结点值在该范围中的结点。

Example 1:

Input:            
    1
   / \
  0   2
  L = 1
  R = 2

Output: 
    1
      \
       2

Example 2:

Input: 
    3
   / \
  0   4
   \
    2
   /
  1
  L = 1
  R = 3

Output: 
      3
     / 
   2   
  /
 1
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if(root == NULL) return NULL;
        if(root->val < L) return trimBST(root->right, L, R);
        if(root->val > R) return trimBST(root->left, L, R);
        root->left = trimBST(root->left, L, R);
        root->right = trimBST(root->right, L, R);
        return root;
    }
};
2、二叉查找树的第 k 个元素

230. Kth Smallest Element in a BST(Medium)
Example 1:

Input: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2

Output: 1

Example 2:

Input: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
 
Output: 3

主要思想是中序遍历,遍历到第 k 个元素的时候,将这个元素保留下来。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        count = k;
        int res = 0;
        midpreview(root, res);
        return res;  
    }
    void midpreview(TreeNode* root, int &res){
        if(root->left != NULL)
            midpreview(root->left, res);
        count--;
        if(count == 0) res = root->val;
        if(res == 0 && root->right != NULL)
            midpreview(root->right, res);
    }
private:
    int count;
};
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        if(root == NULL || k <= 0)
            return 0;
         return Middle(root, k);  
    }
    int Middle(TreeNode* root, int &k){
        int res = 0;
        if(root->left != NULL)
            res = Middle(root->left, k);
        if(k == 1) res = root->val;
        k--;
        if(res == 0 && root->right != NULL)
            res = Middle(root->right, k);
        return res;
    }
};
3、把二叉查找树每个节点的值都加上比它大的节点的值

538. Convert BST to Greater Tree(Easy)
对于每个二叉树的结点,将其值加上二叉树上所有大于该值的节点值。
Example:

Input: The root of a Binary Search Tree like this:
              5
            /   \
           2     13

Output: The root of a Greater Tree like this:
             18
            /   \
          20     13

方法一
先遍历右子树,再遍历左子树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        if(root){
            if(root->right)
                convertBST(root->right);
            sum += root->val;
            root->val =sum;
            if(root->left)
                convertBST(root->left);
        }
        return root;
    }
private:
    int sum = 0;
};

时间复杂度:O(n)
空间复杂度:O(n), 调用堆栈将增长

方法二:
用栈代替递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        int sum = 0;
        stack<TreeNode*>s;
        TreeNode *cur = root;
        while(!s.empty() || cur){
            while(cur){
                s.push(cur);
                cur = cur->right;
            }
            cur = s.top();
            s.pop();
            sum += cur->val;
            cur->val = sum;
            cur = cur->left;
        }
        return root;
    }
};

时间复杂度:O(n)
空间复杂度:O(n)

4、二叉查找树的最近公共祖先

235. Lowest Common Ancestor of a Binary Search Tree (Easy)
Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
Leetcode题解-数据结构-树(BST)_树形结构
Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.

Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

Note:

  • All of the nodes’ values will be unique.
  • p and q are different and both values will exist in the BST.

解题思路
树是二叉查找树,当根节点的值介于两结点的值之间时,该结点就是最近的公共祖先,若两节点的值都大于根节点,要找的公共子节点在右子树中,若两节点的值都小于根节点,要找的公共子节点在左子树中。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root->val>p->val && root->val>q->val)
            return lowestCommonAncestor(root->left,p,q);
        if(root->val<p->val && root->val<q->val)
            return lowestCommonAncestor(root->right,p,q);
        return root;
    }
};
5、二叉树的最近公共祖先

236. Lowest Common Ancestor of a Binary Tree(Medium)
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
Leetcode题解-数据结构-树(BST)_leetcode题解_02
Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Note:

  • All of the nodes’ values will be unique.
  • p and q are different and both values will exist in the binary tree.

解题思路
用递归解决,问题分解为查看子树中是否存在结点p或者q。从根节点开始遍历,循环终止条件为结点p和q中的任一个和root匹配。分别递归左、右子树,查看左右子树中是否有结点p或者q,如果两个结点分别存在左右子树中,root就是公共结点,如果两个节点都出现在左子树,则说明最近公共祖先在左子树中,否则在右子树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL||root==p||root==q)//发现目标节点
            return root;
        TreeNode* left=lowestCommonAncestor(root->left,p,q);
        TreeNode* right=lowestCommonAncestor(root->right,p,q);
        if(left!=NULL&&right!=NULL) //右子树都有目标结点,公共祖先是本身
            return root;
        if(left!=NULL)				//发现了目标节点,继续向上标记为该目标节点  
            return left;
        else
            return right;
    }
};
6、 有序数组构造二叉查找树

108. Convert Sorted Array to Binary Search Tree(Easy)
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example:

Given the sorted array: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
      0
     / \
   -3   9
   /   /
 -10  5

构造出高度平衡的二叉查找,对于每个结点,其左右子树的高度差不能超过1

解题思路:每次将数组中的元素作为根节点,将剩下的元素分为两个区间,分别构造根节点的左子树和右子树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        int n = nums.size();
        return BST(nums, 0, n-1);
    }
    TreeNode *BST(vector<int>& nums, int left, int right){
        if(left > right) return NULL;
        int mid = left + (right - left)/2;
        TreeNode *p = new TreeNode(nums[mid]);
        p->left = BST(nums, left, mid-1);
        p->right = BST(nums, mid+1, right);
        return p;
    }
};
7、 有序链表构造二叉查找树

109. Convert Sorted List to Binary Search Tree(Medium)
Example:

Given the sorted linked list: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
      0
     / \
   -3   9
   /   /
 -10  5

方法一
如果链表长度为0或1,直接构造数,返回。如果长度大于1,每次将链表分为三部分,取链表中间元素构造根节点,左侧链表构建左子树,右侧链表构建右子树。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        if(head == NULL) return NULL;
        if(head->next == NULL){
            TreeNode *root = new TreeNode(head->val);
            root->left = root->right = NULL;
            return root;
        }
        ListNode* p = head;
        int count = 0;
        while(p){
            count++;
            p = p->next;
        }
        p = head;
        for(int i = 1; i < count/2; i++)
            p = p->next;
        ListNode *newhead = p->next->next;
        TreeNode *root = new TreeNode(p->next->val);
        p->next = NULL;
        root->left = sortedListToBST(head);
        root->right = sortedListToBST(newhead);
        return root;
    }
};

时间复杂度: O(Nlog N)
空间复杂度: O(log N),使用递归栈占用的空间

方法二
将链表转化为数组,这样寻找中间元素就可以在O(1)时间内找到

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        listtovector(head);
        return vectorToBST(0, vec.size()-1);
    }
private:
    TreeNode* vectorToBST(int left, int right){
        if(left > right)
            return NULL;
        int mid = left + (right-left)/2;
        TreeNode *root = new TreeNode (vec[mid]);
        root->left = vectorToBST(left, mid-1);
        root->right = vectorToBST(mid+1, right);
        return root;
    }
    void listtovector(ListNode* head){
        while (head){
            vec.push_back(head->val);
            head = head->next;
        }
    }
    vector<int>vec;
};

时间复杂度: O(N)
空间复杂度: O(N)

方法三:模拟中序遍历
中序遍历的结果就是对二叉搜索树按数据大小访问的结果。这里我们模拟中序遍历的过程。通过使用(l + r)/ 2来找出中间元素。这里并没有真正找到链表的中间节点。使用 l, r, mid 只是告诉我们改结点在链表中的什么位置。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        int size = getsize(head);
        cur = head;
        return convertListToBST(0, size-1);
    }
private:
    int getsize(ListNode* head){
        ListNode *p = head;
        int count = 0;
        while(p){
            count++;
            p = p->next;
        }
        return count;
    }
    TreeNode* convertListToBST(int l, int r) {
        if (l > r) return NULL;
        int mid = (l + r) / 2;
        TreeNode *left = convertListToBST(l, mid - 1);
        TreeNode *node = new TreeNode(cur->val);
        node->left = left;
        cur = cur->next;
        node->right = convertListToBST(mid + 1, r);
        return node;
    }
    ListNode* cur;
};

时间复杂度: O(N)
空间复杂度: O(logN)

8、寻找两个点,和为给定值

653. Two Sum IV - Input is a BST(Easy)
Example 1:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7

Target = 9

Output: True

Example 2:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7

Target = 28

Output: False

解题思路:用中序遍历将二叉树的值,有序的放到数组中,再用双指针寻找和为给定值的节点是否存在。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        TreeToVector(root);
        int n = vec.size();
        int i = 0, j = n - 1;
        while(i < j){
            if(vec[i] + vec[j] == k)
                return true;
            else if(vec[i] + vec[j] > k)
                j--;
            else
                i++;
        }
        return false;
    }
private:
    vector<int>vec;
    void TreeToVector(TreeNode* root){
        if(root == NULL) return;
        if(root->left)
            TreeToVector(root->left);
        vec.push_back(root->val);
        if(root->right)
            TreeToVector(root->right);
    }
};

时间复杂度: O(N)
空间复杂度: O(N)

9、二叉搜索树中两节点差的最小值

530. Minimum Absolute Difference in BST(Easy)
Given a binary search tree with non-negative values, find the minimum absolute difference between values of any two nodes.
Example:

Input:

   1
    \
     3
    /
   2

Output:
1

Explanation:
The minimum absolute difference is 1, which is the difference between 2 and 1 (or between 2 and 3).

解题思路:中序遍历,求解两相邻节点差的最小值,每次保留上一次访问的节点,本次节点值减去上次节点值,差的最小值。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        getmindif(root);
        return mindif;
    }
private:
    TreeNode* pre = NULL;
    int mindif = 65535;
    void getmindif(TreeNode* root){
        if(root == NULL) return;
        if(root->left) getmindif(root->left);
        if(pre) mindif = min(mindif, root->val - pre->val);
        pre = root;
        if(root->right) getmindif(root->right);
    }
    
};
10、寻找二叉查找树中出现次数最多的值

501. Find Mode in Binary Search Tree(Easy)

For example:
Given BST [1,null,2,2],

   1
    \
     2
    /
   2

return [2].

出现次数最多的值不止一个时,全部返回,可以以任何顺序返回。不能开辟额外的空间,递归占用的空间不算。

解题思路
采用中序遍历,从小到大访问二叉搜索树中的元素,记录上一个不一样的元素大小,记录当前元素大小,当前元素大小变化时,查看元素出现的个数,如果大于前面的记录,清空记录并更新,如果个数相等,将该元素也加入。
这里别忘了比较最后一个元素出现的次数。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> findMode(TreeNode* root) {
        if(root == NULL) return res;
        getmode(root);
        if (count > maxcount){		//比较最后一个元素出现的次数
            res.clear();
            res.push_back(pre->val);
        }
        else if (count == maxcount)
            res.push_back(pre->val);
        return res;
    }
private:
    void getmode(TreeNode* root){
        if (root == NULL) return;
        if (root->left) getmode(root->left);
        if (pre){
            if (root && root->val == pre->val)
                count++;
            else {
                if (count > maxcount){ 		//大于前面的记录,清空并加入
                    maxcount = count;
                    res.clear();
                    res.push_back(pre->val);
                }
                else if (count == maxcount)	//等于前面的记录,加入
                    res.push_back(pre->val);
                pre = root;					//别忘了更新状态
                count = 0;
            }
        }
        else
            pre = root;						//第一个元素
        if (root->right) getmode(root->right);
    }
    vector<int>res;
    TreeNode* pre = NULL;
    int count = 0;
    int maxcount = 0;
};