这是一道面试的算法题,题目不难,但是在面试的时候是要求直接在白板上写程序,感觉自己还是弱爆了。第一次体验这种面试方式,虽然被虐,但是感觉还是挺好的,这方面的经验还是需要积累。
题目: 在一个二叉搜索树种查找比某个数(K)大数中最小的那个。
先把二叉树相关的构造代码贴上,下面是二叉树的节点定义。
/**
*节点
*/
public class Node {
private int data;
private Node lChild, rChild;
public Node (int data){
this.data = data;
this.lChild = null;
this.rChild = null;
}
public Node(int data, Node l, Node r){
this.data = data;
this.rChild = r;
this.lChild = l;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLChild() {
return lChild;
}
public void setLChild(Node lChild) {
this.lChild = lChild;
}
public Node getRChild() {
return rChild;
}
public void setRChild(Node rChild) {
this.rChild = rChild;
}
}
下面是二叉树定义, 构造,以及三种遍历方法。
public class BinTree {
private Node root;
public BinTree(){
root = null;
}
/**
* 创建搜索二叉树
* @param node
* @param data
*/
private void BuildBinTree(Node node, int data){
if(root == null){
root = new Node(data);
}else{
if(data > node.getData()){
if(node.getRChild() == null)
node.setRChild(new Node(data));
else
BuildBinTree(node.getRChild(), data);
}else{
if(node.getLChild() == null)
node.setLChild(new Node(data));
else
BuildBinTree(node.getLChild(), data);
}
}
}
public void BuildBinTree(int[] arr){
for(int i:arr)
BuildBinTree(root, i);
}
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
/**
* 递归_先序遍历
* @param node
*/
public void PreOrderTraverse(){
if(root != null){
System.out.print("先序遍历:");
this.PreOrderTraverse(root);
System.out.println();
}else
System.out.println("Error! This tree is empty...");
}
private void PreOrderTraverse(Node node){
if(node != null){
System.out.print(node.getData()+" ");
PreOrderTraverse(node.getLChild());
PreOrderTraverse(node.getRChild());
}
}
/**
* 递归_中序遍历
* @param node
*/
public void InOrderTraverse(){
if(root != null){
System.out.print("中序遍历:");
this.InOrderTraverse(root);
System.out.println();
}else
System.out.println("Error! This tree is empty...");
}
private void InOrderTraverse(Node node){
if(node != null){
InOrderTraverse(node.getLChild());
System.out.print(node.getData()+" ");
InOrderTraverse(node.getRChild());
}
}
首先对于这个题目,最小白的方法就是把二叉树变成一个有序数组(中序遍历)O(n),在有序数组中进行二分查找O(logn)。
这里重点是第二种方法,在树结构中进行查找, 感觉这个问题,和二叉树中插入新节点的过程是类似的,大致如下:
- 定义节点node, 并将根节点赋值给node;
- 如果node.data > K, 将node.data暂存在临时变量中,并转向左子树;
- 如果node.data < K , 转向右子树;
- 重复步骤2和步骤3直到叶子节点
这里需要注意的是,必须要遍历到叶子节点,这个过程其实就是一个二分查找的过程,复杂度O(logn).这里我设置了一个标记,就是如果是空树则返回 0.
/**
* 查找比key大的最小的数
* @param tree:二叉搜索树
* @param key:要查找的数
* @return:返回最终值
*/
public static int FindMinOfMax(BinTree tree, int key){
Node node = tree.getRoot();
int temp = 0;
if(node == null)
return temp;
while(node != null){
if(node.getData() > key)
temp = node.getData();
if(node.getData() > key){
node = node.getLChild();
}else{
node = node.getRChild();
}
if(node == null)
break;
}
return temp;
}