LeetCode 热题 100_二叉搜索树中第 K 小的元素(44_230)
题目描述:
给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。
输入输出样例:
示例 1:
输入 :root = [3,1,4,null,2], k = 1
输出:1
示例 2:
输入 :root = [5,3,6,2,4,null,null,1], k = 3
输出:3
提示:
树中的节点数为 n 。
1 <= k <= n <= 10^4^
0 <= Node.val <= 10^4^
题解:
解题思路:
思路一(中序遍历(递归)+数组):
1、因二叉搜索树采用中序遍历的方式遍历的数据是有序且递增的,所以采用递归的中序遍历将结点存储在数组中,再取数组中的第k个元素。
2、复杂度分析:
① 时间复杂度:O(n), n代表树中的节点数,需遍历整个二叉树将结点信息存入数组中所以为O(n),取数组第k个元素的时间为O(1)。
② 空间复杂度:O(n),递归的中序遍历需要 O(logn)~O(n),数组需要存储每个结点的信息O(n)。
思路二(中序遍历(非递归)):
1、在进行非递归中序遍历时,我们可以记录遍历节点的个数,记录的个数来判断当前元素是否是二叉搜索树中第 k 小的元素。当然我们也可以通过遍历一个元素就将k值减小,当k值减小到0时也就是我们要找的元素。
3、复杂度分析
① 时间复杂度:O(k), k代表要取第k小的元素。当我们遍历到第k小的元素时就可以进行返回。
② 空间复杂度:O(n),非递归中序遍历需要栈来存储结点,最坏的情况栈存储n个结点。
代码实现
代码实现(思路一(中序遍历(递归)+数组)):
cpp
//方法一(递归):采用中序遍历将结点存储在数组中,再取数组中的第k个元素
int kthSmallest1(TreeNode* root,int k) {
//nums用于存储中序遍历数据
vector<int> nums;
//通过中序遍历将数据存储到nums
inorder(root,nums);
//返回第k小的元素
return nums[k-1];
}
//将元素按中序遍历顺序存入数组nums中
void inorder(TreeNode *root,vector<int> &nums){
if(root==nullptr) return;
inorder(root->left,nums);
nums.emplace_back(root->val);
inorder(root->right,nums);
}
代码实现(思路二(中序遍历(非递归))):
cpp
//方法二(非递归):中序遍历,遍历到第k个时停止
int kthSmallest2(TreeNode *root,int k){
//判断树是否为空
if(root==nullptr){
throw invalid_argument("Tree is empty.");
}
stack<TreeNode *> stk;
while (root!=nullptr||!stk.empty())
{
while (root!=nullptr)
{
stk.push(root);
root=root->left;
}
root=stk.top();
stk.pop();
//每中序遍历访问一个元素将k的值-1,当k=0时正好就是第k小的元素,结束遍历
--k;
if(k==0){
return root->val;
}
root=root->right;
}
//如果遍历完成也没有找到第k小的元素,则返回异常
throw out_of_range("k is larger than the number of nodes in the tree.");
}
以思路一完成代码调试
cpp
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
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){}
};
//通过数组创建二叉树(数组元素为-1代表nullptr)
TreeNode *creatTree(vector<int> nums){
if(nums.empty()) return nullptr;
TreeNode *root=new TreeNode(nums[0]);
queue<TreeNode *> q;
q.push(root);
int i=1;
while (i<nums.size())
{
TreeNode *node=q.front();
q.pop();
if(i<nums.size()&&nums[i]!=-1){
node->left=new TreeNode(nums[i]);
q.push(node->left);
}
++i;
if(i<nums.size()&&nums[i]!=-1){
node->right=new TreeNode(nums[i]);
q.push(node->right);
}
++i;
}
return root;
}
//中序遍历输出二叉树(用于验证二叉树是否创建成功)
void inorder_print(TreeNode *root){
if(root==nullptr) return ;
inorder_print(root->left);
cout<<root->val<<" ";
inorder_print(root->right);
}
class Solution
{
public:
//方法一(递归):采用中序遍历将结点存储在数组中,再取数组中的第k个元素
int kthSmallest1(TreeNode* root,int k) {
//nums用于存储中序遍历数据
vector<int> nums;
//通过中序遍历将数据存储到nums
inorder(root,nums);
//返回第k小的元素
return nums[k-1];
}
//将元素按中序遍历顺序存入数组nums中
void inorder(TreeNode *root,vector<int> &nums){
if(root==nullptr) return;
inorder(root->left,nums);
nums.emplace_back(root->val);
inorder(root->right,nums);
}
};
int main(){
vector<int> nums={3,1,4,-1,2};
//通过数组创建二叉树
TreeNode *root=creatTree(nums);
//中序遍历输出二叉搜索树(验证二叉搜索树创建是否正确)
//inorder_print(root);
//搜索二叉树中第k小的元素并输出
Solution s;
int k=1;
cout<<s.kthSmallest1(root,k);
return 0;
}
LeetCode 热题 100_二叉搜索树中第 K 小的元素(44_230)原题链接
欢迎大家和我沟通交流(✿◠‿◠)