早就在优快云的网摘上看到《[置顶]横空出世,席卷互联网--评微软等公司数据结构和算法面试100题》这篇文章,想着找工作联系算法的时候一定好好看看。终于看完了数据结构的基础之后,挤出一些时间来,做做这些题目,感受一下大公司笔面的算法题。其实自己算法方便一直比较薄弱,所以只是尝试一下吧。
接触的第一门语言是C++,但是上研之后,实验室一直用Java,也就基本没怎么用C++,导致现在对C++越来越生疏。对于这种算法题目,我也是用Java实现的。自我感觉对Java还是比较熟悉的,尤其Eclipse开发环境非常方便啊。把我写的实现贴出来,不知道会不会有人看啊
第一道题:
1. 把二元查找树转变成排序的双向链表
题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16 。
首先我们定义的二元查找树 节点的数据结构如下:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
对于这道题,我首先采用二元查找树的中序遍历的非递归实现方法实现了一遍,虽然没有创建任何其他结点,但是我使用了栈。
然后参考了提供的答案中的思想,采用二院搜索树的递归实现来做,这样确实不需要多余的存储空间,只需要多加几个指针(Java中是引用)即可。
package test.interview.algorithm;
import java.util.Stack;
public class Problem1 {
/**
* 1. 把二元查找树转变成排序的双向链表
* 题目:
* 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
* 要求不能创建任何新的结点,只调整指针的指向。
*
* @ZJ思路:二元查找树的中序遍历就是排序序列,修改指针的指向,即可得到有序双向表
*
* @param args
*/
static DoubleList list = new DoubleList();
public static void main(String[] args) {
// TODO Auto-generated method stub
// 用非常简单的方法构建一棵二叉树
int[] a = {10,6,14,4,8,12,16};
BSTreeNode node4 = new BSTreeNode(4,null,null);
BSTreeNode node8 = new BSTreeNode(8,null,null);
BSTreeNode node6 = new BSTreeNode(6,node4,node8);
BSTreeNode node12 = new BSTreeNode(12,null,null);
BSTreeNode node16 = new BSTreeNode(16,null,null);
BSTreeNode node14 = new BSTreeNode(14,node12,node16);
BSTreeNode node10 = new BSTreeNode(10,node6,node14);
BSTreeNode node;
// 这是用非递归中序遍历的方法实现的
// node = BinaryTreeToDoubleList(node10);
//
// for(;node!=null;node=node.m_pLeft){
// System.out.print(node.m_nValue+",");
// }
// 采用递归的中序遍历实现的
inorderTranvers(node10);
node = list.head;
for(;node!=null;node=node.m_pRight){
System.out.print(node.m_nValue+",");
}
}
// 采用中序遍历的非递归实现,使用了栈,不知道可不可以
public static BSTreeNode BinaryTreeToDoubleList(BSTreeNode root){
Stack<BSTreeNode> s = new Stack<BSTreeNode>();
BSTreeNode node = root; // 记录当前结点
BSTreeNode prev = null; // 记录当前结点的前一个结点,初始化为null,便于后面判断
while(node!=null||!s.isEmpty()){
if(node!=null){
s.push(node);
node = node.m_pLeft;
}
else{
node = s.pop();
if(prev==null){
prev = node;
}else{
prev.m_pRight = node;
node.m_pLeft = prev;
prev = node;
}
node=node.m_pRight;
}
}
return prev;
}
/**
* 答案中的思想,采用中序遍历递归实现,没有采用多余的存储空间
* 采用了全局变量双链表,其实还是比较容易的,很多东西只要敢想,就能做出来!!!
*
* @param root
* @return
*/
public static void inorderTranvers(BSTreeNode node){
if(node!=null){
inorderTranvers(node.m_pLeft);
addToDoubleList(node);
inorderTranvers(node.m_pRight);
}
}
private static void addToDoubleList(BSTreeNode node){
// 这里使用current指针指向上一次的当前结点,其实就充当了前一个结点的角色
if(list.head==null){ // 第一次调用函数,那么双向链表的头为空,
list.head = node;
list.current = node;
}else{
list.current.m_pRight = node;
node.m_pLeft = list.current;
list.current = node;
}
}
}
class DoubleList{
BSTreeNode head;
BSTreeNode current;
BSTreeNode tail;
}
class BSTreeNode
{
public BSTreeNode(int value,BSTreeNode left,BSTreeNode right){
m_nValue = value;
m_pLeft = left;
m_pRight = right;
}
int m_nValue; // value of node
BSTreeNode m_pLeft; // left child of node
BSTreeNode m_pRight; // right child of node
};