昨天做了个二叉树的笔试题 大概十几分钟就做完了 但是有些疑惑 想到了一个新题 不知道有没有人能解

2015-06-15 22:13:39 +08:00
 woai110120130
下面是笔试题目: 根据用户的输入的字母, 构建一个满二叉树, 然后打印出它的所有从根到叶子的路径. (假设用户的输入字母的个数恰好满足构建一个满二叉树)
例如: 输入 a b c d e f g后构建成下面的树
a
b c
c d e f 就是这样的一个满二叉树

然后输出 abc,abd,ace,acf
要求: 使用任意一种你熟悉的语言即可。
然后菜鸟我是这样做的

/**
* Created by tangtang on 15/6/15.
*/
public class Tree {


public static void main(String[] args)
{
byte[] byteArray={'D','B','A','C','F','E','G'};

Node root=new Node();




for (byte b: byteArray)
{
root.insert(b);

}

root.traverseBiTree("");
}


static class Node{

private byte value=-1;

private Node leftChild;
private Node rightChild;

public Node getLeftChild()
{
return leftChild;
}

public Node getRightChild()
{
return rightChild;
}


public byte getValue()
{
return value;
}

public void setLeftChild(Node leftChild)
{
this.leftChild=leftChild;
}

public void setRightChild(Node rightChild)
{
this.rightChild=rightChild;
}

public void setValue(byte value)
{
this.value=value;
}


/**
* 遍历加打印 遍历路径
* 思路 让上一层都产生一个string
* @return
*/
public void traverseBiTree(String str)
{
str+=(char)value;
if (leftChild==null&&rightChild==null) {
System.out.println(str);
return;
}

if (leftChild!=null)
{
leftChild.traverseBiTree(str);
}

if (rightChild!=null)
{
rightChild.traverseBiTree(str);
}
}




public void insert(byte c)
{
if (value==-1) {
value = c;
return;
}

if (c>value)
{
if (rightChild==null)
rightChild=new Node();
rightChild.insert(c);
}else {
if (leftChild==null)
leftChild=new Node();
leftChild.insert(c);
}

}

}
}

用java写的 有点长 不过去掉set get方法也非常简洁了


在做的过程产生了这样一个问题
如果 试题问的 就是输入a b c d e f g 生成上边的那个满二叉树 要求下一层的孩子都大于上一层的孩子 并且 右孩子都大于左孩子 如何生成该 上面的那个满二叉树? 好好想想 这个问题还是很困难的
要求只能一个一个的插入 不可以先排序再生成二叉树
6237 次点击
所在节点    程序员
56 条回复
zwzmzd
2015-06-15 23:33:43 +08:00
再者,基于比较的排序算法已经证明了时间复杂度下界是O(nlogn)。你要的结果里面所有元素已经有序了,所以如果你的算法基于比较,也不可能超过这个下界。
binux
2015-06-15 23:36:12 +08:00
@Heartwork 并不违反 「下一层的孩子都大于上一层的孩子 并且 右孩子都大于左孩子」吧,那有什么关系?
zwzmzd
2015-06-15 23:37:08 +08:00
@binux
@Heartwork
只交换是不行的,但再加上向下调整就行了
binux
2015-06-15 23:40:46 +08:00
@zwzmzd 为什么不行?首先小根堆保证了左右两个元素比父元素大,交换了依然满足这个条件啊。
Heartwork
2015-06-15 23:45:26 +08:00
@binux
说反了,应该是 无法避免a的兄弟节点的孩子比a小的状况

这样:

a
b z
c d
c和d是b的孩子,但是比z小。
zwzmzd
2015-06-15 23:46:28 +08:00
@binux 就说一个简单的小根堆 1,5,2,6,7,3,4 (数组表示)
交换中间层元素5,2之后,会变成 1,2,5,6,7,3,4,不符合小根堆性质了

结论:已经调整完毕的小根堆,不可随意交换某两个孩子的位置。
Heartwork
2015-06-15 23:48:50 +08:00
有序的完全二叉树为一有序序列,在插入过程中插入位置之后的节点都需要向后移动,所以这个题目等同于求一个有序数组的插入算法…

这样应该没问题了。
woai110120130
2015-06-15 23:51:12 +08:00
@zwzmzd 其实说不能先排序 是考虑到性能的问题 每次都要排序 会浪费极大的性能 其实这也不是真实中需要的算法了 只不过是在做题的过程中产生的思考罢了 看了楼上的 觉得还没有满意的答案 为什么没有人动手实现一下呢 想的永远回比做起来简单
woai110120130
2015-06-15 23:54:52 +08:00
@Heartwork bingo 其实这么做 把先排序换成了后排序 我在想有没有更好的办法
Heartwork
2015-06-16 00:03:31 +08:00
后排序会导致插入过程中树无法保持有序的条件,这个题目就退化为给一个数组排序了。

底层如果使用二叉树的话,需要维护每一个元素的“前驱”和“后继”,前驱和后继指value的前一个和后一个。

这样插入时需要遍历插入位置之后的元素,复杂度和数组的相同。
binux
2015-06-16 00:05:35 +08:00
@Heartwork
@zwzmzd 难道 「下一层的孩子都大于上一层的孩子」 这句话的意思是,大于上一层的所有节点?
woai110120130
2015-06-16 00:07:31 +08:00
@Heartwork 洗澡的时候想了想 这并没有什么卵用 排完序之后 还需要重新组织二叉树 还是违背题的
Heartwork
2015-06-16 00:08:58 +08:00
@binux

我是这样理解的。就是一颗有序的完全二叉树。
woai110120130
2015-06-16 00:09:35 +08:00
@Heartwork 亲 你觉得可行 可以写出来让大家学习学习
Heartwork
2015-06-16 00:09:54 +08:00
@woai110120130
所以底层用数组就行了
binux
2015-06-16 00:39:02 +08:00
@Heartwork

1、如果这么理解,这个题目是有问题的。
既然第 n 层 全部大于 第 n-1 层,「右孩子都大于左孩子」没有任何意义,在同一层之间交换元素,没有任何影响和副作用。那么这个 「右孩子都大于左孩子」的要求,随便交换一下元素就可以了。

2、其次,这个问题不是完全排序的。
只要使用快速划分,让数组左边一半小于右边一半,然后对左边继续前面的过程。再加上1所诉的的交换元素,就可以建立起符合要求的树了。复杂度只有 O(n)
woai110120130
2015-06-16 08:41:56 +08:00
楼上的诸位说这么多只不过是纸上谈兵罢了 没有一个肯做出来用事实说话
Heartwork
2015-06-16 08:45:08 +08:00
@binux
n层大于n-1层(a)与右孩子大于左孩子(b)是两个独立的条件,写两个例子。
a成立b不成立:
a
c b
b成立a不成立:
b
a c
这两个条件共同约束下只能是有序序列。
Heartwork
2015-06-16 08:48:00 +08:00
@binux
对了,你说的2的“调整”如果满足a和b,就是一个快速排序。
binux
2015-06-16 09:03:12 +08:00
@woai110120130 事实?你自己问题都说不清楚,让人家找事实?你写得出测试用例吗?

@Heartwork 不是的
a
b c
d e f g
成立

a
b c
e g d f
也成立

同层之间,只要 2n 和 2n+1 做个交换就能满足条件 b

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/198803

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX