Tencentバックエンドインターン開発インタビュークール:バイナリ検索ツリーでk番目に大きいノード

初めての面接です。これまで面接を見たことがないか、ojをブラッシングしたことがありません。結果はまったく予想外です。今度は、ガチョウの農場で失業したことを記念して、この質問を記録します。

質問:
二分探索木が与えられた場合、その中でk番目に大きいノードを見つけてください。たとえば、次の図では、3番目に大きいノードの値は4です。

ここに画像の説明を挿入
まず第一に、二分探索木とは何ですか?

Baidu百科事典の定義:二分探索木は、空の木、または次のプロパティを持つ二分木です。左側のサブツリーが空でない場合、左側のサブツリーのすべてのノードの値は、ルートの値よりも小さくなります。ノード、その右のサブツリーが空でない場合、その右のサブツリー上のすべてのノードの値はそのルートノードの値よりも大きく、その左と右のサブツリーもそれぞれ二分木です。

二分探索木である場合、非常に重要な特性は、二分探索木の順方向の走査が数値の昇順であるということです。
私がインタビューを行っていたとき、私は何をすべきかさえ知りませんでした。

次に、バイナリソートツリーでk番目に大きいノードを見つけるには、バイナリツリーを順番にトラバースするだけで済み、バイナリツリーでk番目に大きいノードを見つけることができます。

public class TreeNode {
    
    
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int x) {
    
    
        val = x;
    }
}



public class 二叉搜索树的第k大节点 {
    
    
    private static int mK;

    public static TreeNode kThNode(TreeNode root, int k) {
    
    
        if (root == null || k == 0) {
    
    
            return null;
        }
        mK = k;
        return findKthNode(root);
    }

    /**
     * 使用递归的方式进行求解
     *
     * @param root 根节点
     * @return 第k大节点
     */
    private static TreeNode findKthNode(TreeNode root) {
    
    
        TreeNode target = null;

        // 左子树不为空的时候递归寻找
        if (root.left != null) {
    
    
            target = findKthNode(root.left);
        }
        // 当没有找到目标的时候,我们需要对k-1
        if (target == null) {
    
    
            if (mK == 1) {
    
    
                return root;
            }
            mK--;
        }

        // 没有找到目标并且右子树不为空的时候,递归地在右子树中寻找
        if (target == null && root.right != null) {
    
    
            target = findKthNode(root.right);
        }
        return target;
    }

    /**
     * 使用非递归的方式进行求解
     *
     * @param root 根节点
     * @param k    k表示第k大元素
     */
    public static void findKthNumber(TreeNode root, int k) {
    
    
        TreeNode temp = root;
        int result = 0;
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || temp != null) {
    
    
            // 沿着左子树走到尽头
            while (temp != null) {
    
    
                stack.push(temp);
                temp = temp.left;
            }
            // 左分支走到尽头,开始遍历右分支
            if (!stack.isEmpty()) {
    
    
                temp = stack.pop();
                result++;
                if (result == k) {
    
    
                    System.out.print(temp.val + " ");
                    return;
                }
                temp = temp.right;
            }
        }
    }

    public static void main(String[] args) {
    
    
        TreeNode root=new TreeNode(5);
        TreeNode node3=new TreeNode(3);
        TreeNode node2=new TreeNode(2);
        TreeNode node4=new TreeNode(4);
        root.left=node3;
        node3.left=node2;
        node3.right=node4;
        System.out.println(kThNode(root,3).val); //输出4
    }
}

やった後、難しくないことがわかりました

おすすめ

転載: blog.csdn.net/liu_12345_liu/article/details/103113182