[剑指offer] 二叉搜索树的第k大节点(C++解法)

给定一棵二叉搜索树,请找出其中第k大的节点。

示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4

示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 4

限制:
1 ≤ k ≤ 二叉搜索树元素个数

递归解法:

思路:先按中序遍历将二叉搜索树的结点值从小到大的顺序保存在vec数组中,然后直接输出第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 kthLargest(TreeNode* root, int k) {
        vector<int> vec;
        inorder(root, vec);
        return vec[vec.size() - k];
    }
    void inorder(TreeNode* node, vector<int>& vec) {
    	//中序遍历,将节点按从小到大顺序保存在vec中
        if (node->left)
            inorder(node->left, vec);
        vec.push_back(node->val);
        if (node->right)
            inorder(node->right, vec);
    }
};

非递归解法:

思路:类似于中序遍历的非递归算法,但是访问结点的顺序为:右子结点 -> 父节点 -> 左子结点。首先设定一个计数器cnt = 1, 然后循环向右遍历结点,将访问到的结点顺序压入栈中,直到右子结点为空。然后出栈,只要当前计数器cnt等于k,则找到了第k大的结点,否则计数器加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:
    int kthLargest(TreeNode* root, int k) {
        vector<int> vecInt;
        stack<TreeNode*> s;
        TreeNode* node = root;
        int cnt = 1;
        while (node || !s.empty()) {
            while (node) {
            	//向右遍历获取值最大的结点
                s.push(node);
                node = node->right;
            }
            if (!s.empty()) {
            	//出栈判断
                node = s.top();
                if (cnt == k)
                    return node->val;
                else 
                    ++cnt;
                s.pop();
                //向当前出栈结点的左子树重复上述步骤
                node = node->left;
            }
        }
        return 0;
    }
};

你可能感兴趣的:(力扣刷题)