【leetcode】【medium】230. Kth Smallest Element in a BST​​​​​​​

本文探讨了在二叉搜索树中寻找第K小元素的有效算法,包括递归、非递归中序遍历及修改节点数据结构三种方法。通过实例展示了不同方法的应用,并对比了它们的优劣。

230. Kth Smallest Element in a BST

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

Note:
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

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

Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

题目链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/solution/

 

思路

对BST中序遍历可得到递增序列,因此总体的解题思路是借助中序遍历,在中序是判断当前节点是否是第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) {
        return findk(root, k)->val;
    }
    TreeNode* findk(TreeNode* root, int &k){
        if(!root) return NULL;
        auto l = findk(root->left, k);
        --k;
        if(k==0) return root;
        auto r = findk(root->right, k);
        return (l?l:r);
    }
};

法二:非递归

对中序遍历用非递归方法实现。

我想到的方法:在遍历到父节点时,不能将自身弹出,在将左孩子入栈前先加一个空节点,用来标记当前节点已经历第一次遍历,使得在下一次遍历(中序)的时候访问完就弹出。

别人的方法:套两个while循环,一个管不断将左孩子压栈,一个管整个树的遍历是否完成。

参考:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/solution/er-cha-sou-suo-shu-zhong-di-kxiao-de-yuan-su-by-le/

明显别人的方法比我的优雅许多,里层while就是对压栈思路的原始翻译,两个while嵌套的使用学习下。

非迭代的运行速度更快,可以在找到元素时直接终止程序。

/**
 * 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) {
        stack<TreeNode*> record;
        while(true){
            while(root){
                record.push(root);
                root = root->left;
            }
            root = record.top();
            record.pop();
            if(--k == 0) return root->val;
            else root = root->right;
        }
    }
};

 

法三:修改节点数据结构

题目最后问频繁根据排名查找元素,可以在节点数据结构中加一个变量:记录以当前节点为根节点的子树上有多少个节点。

则查找时能根据数量关系,直接能确定走向目标节点的路径。

在本题给的数据结构中不太好实现。

通过短时倒谱(Cepstrogram)计算进行时-倒频分析研究(Matlab代码实现)内容概要:本文主要介绍了一项关于短时倒谱(Cepstrogram)计算在时-倒频分析中的研究,并提供了相应的Matlab代码实现。通过短时倒谱分析方法,能够有效提取信号在时间与倒频率域的特征,适用于语音、机械振动、生物医学等领域的信号处理与故障诊断。文中阐述了倒谱分析的基本原理、短时倒谱的计算流程及其在实际工程中的应用价值,展示了如何利用Matlab进行时-倒频图的可视化与分析,帮助研究人员深入理解非平稳信号的周期性成分与谐波结构。; 适合人群:具备一定信号处理基础,熟悉Matlab编程,从事电子信息、机械工程、生物医学或通信等相关领域科研工作的研究生、工程师及科研人员。; 使用场景及目标:①掌握倒谱分析与短时倒谱的基本理论及其与傅里叶变换的关系;②学习如何用Matlab实现Cepstrogram并应用于实际信号的周期性特征提取与故障诊断;③为语音识别、机械设备状态监测、振动信号分析等研究提供技术支持与方法参考; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,先理解倒谱的基本概念再逐步实现短时倒谱分析,注意参数设置如窗长、重叠率等对结果的影响,同时可将该方法与其他时频分析方法(如STFT、小波变换)进行对比,以提升对信号特征的理解能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值