LeetCode 热题 100_二叉搜索树中第 K 小的元素(44_230_中等_C++)(二叉树;中序遍历(递归)+数组;中序遍历(非递归))

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)原题链接

欢迎大家和我沟通交流(✿◠‿◠)

相关推荐
ChoSeitaku5 分钟前
No.6十六届蓝桥杯备战|赋值操作符|连续赋值|复合赋值|类型转换|强制|混合|赋值(C++)
c++·算法·蓝桥杯
勤劳的进取家20 分钟前
区别:支持向量机 (SVM) 和逻辑回归
算法·支持向量机·逻辑回归
萌の鱼21 分钟前
leetcode 2279. 装满石头的背包的最大数量
数据结构·c++·算法·leetcode
--Ekko--22 分钟前
嵌入式入门Day38
c++
sun00770033 分钟前
C++中,typename
开发语言·c++
毒丐1 小时前
GCC使用说明
linux·c语言·c++
S-X-S1 小时前
算法解析-经典150(图论、回溯法)
算法·深度优先·图论
强大的RGG1 小时前
从源码编译Qt5
开发语言·c++·qt
(❁´◡`❁)Jimmy(❁´◡`❁)1 小时前
3103: 【基础】既生瑜,何生亮!
c++