230. 二叉搜索树中第K小的元素

介绍

中序遍历:左子树 -> 中 -> 右子树

二叉搜索树:中序遍历可以得到有序的序列

递归法

1.使用函数循环递归处理

2.使用一个数组来保存 k, 保证在个个递归函数中都能看到 看的变化;每访问一个节点,这个数减一,当数组中的数为1时,即访问到了第k小的数

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public int KthSmallest(TreeNode root, int k) {
        // 辅助结构,当 k == 1 时 表示访问到 第 k个最小的元素
        int[] aux = new int[] { k };
        return Traverse(root, aux);    
    }

    // 递归访问
    public int Traverse(TreeNode node, int[] aux) {
        if(node == null)
        {
            // 用 -1 表示访问到终点
            return -1;
        }

        // 先访问左子树
        {
            var val = Traverse(node.left, aux);
            if(val != -1)
            {
                return val;
            }
        }

        // 访问该节点
        {
            if(aux[0] == 1)
            {
                // 结果
                return node.val;
            }
            aux[0]--;
        }

        // 后访问右子树
        {
            var val = Traverse(node.right, aux);
            if(val != -1)
            {
                return val;
            }
        }

        // 这里是不会走到的根据题意
        return -1;
    }
}

优化:

1.使用 引用传递 k, 确保递归函数都能看到k的变换

2.每次访问右子树时,不用判断直接返回结果

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public int KthSmallest(TreeNode root, int k) {
        // 辅助结构,当 k == 1 时 表示访问到 第 k个最小的元素
        int aux = k;
        return Traverse(root, ref aux);    
    }

    // 递归访问
    public int Traverse(TreeNode node, ref int aux) {
        if(node == null)
        {
            // 用 -1 表示访问到终点
            return -1;
        }

        // 先访问左子树
        {
            var val = Traverse(node.left, ref aux);
            if(val != -1)
            {
                return val;
            }
        }

        // 访问该节点
        {
            if(aux == 1)
            {
                // 结果
                return node.val;
            }
            aux--;
        }

        // 后访问右子树
        // {
        //     var val = Traverse(node.right, ref aux);
        //     if(val != -1)
        //     {
        //         return val;
        //     }
        // }

        // // 这里是不会走到的根据题意
        // return -1;

        // 一个优化,这里直接返回,如果没找到这里就返回-1
        return Traverse(node.right, ref aux);
    }
}

迭代法

1.使用数据结构Stack,模拟真实的栈处理流程

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public int KthSmallest(TreeNode root, int k) {
        // 借助 Stack 模拟栈
        Stack<TreeNode> s = new Stack<TreeNode>();

        // 先让第一个节点进栈,后面流程就处理一致了
        s.Push(root);

        // 根据题意一定存在结果
        // while(s.Count > 0)
        while(true)
        {
            // 访问左子树
            var top = s.Peek();
            if(top != null)
            {
                s.Push(top.left);
                continue;
            }

            // 将null节点弹出栈
            s.Pop();

            // 访问当前节点,这里不用判断 s的数量,根据代码可知,这里至少存在一个节点
            var visit = s.Pop();
            if(k == 1)
            {
                // 第k最小元素
                return visit.val;
            }
            k--;

            // 访问右子树
            s.Push(visit.right);
        }
        return -1;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值