初めての面接です。これまで面接を見たことがないか、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
}
}
やった後、難しくないことがわかりました