1
Heartwork 2015-06-15 22:33:02 +08:00 via Android
听说过平衡二叉树或者红黑树么?它们在插入过程当中通过自旋就能满足你说的要求。
|
2
woai110120130 OP @Heartwork 这位兄台 你实现一个看看 平衡二叉树 并不能满足需求 不信你做做看
|
3
yangff 2015-06-15 22:44:16 +08:00 via Android
treap
|
4
woai110120130 OP @yangff 1.如果v是u的左孩子,则key[v] < key[u].
2.如果v是u的右孩子,则key[v] > key[u]. 3.如果v是u的孩子,则priority[u] > priority[u]. 这是树堆的特点 好像并不满足 |
5
Heartwork 2015-06-15 23:01:36 +08:00
|
6
yangff 2015-06-15 23:03:49 +08:00 via Android
@woai110120130 priority=key
|
7
woai110120130 OP @Heartwork 嗯 我并没有解出来 想的不错 但是一写发现还是有问题
|
8
binux 2015-06-15 23:05:00 +08:00
#!/usr/bin/python
#如果你会用数组表示二叉树,就会知道这个问题有多简单 l = 'abcdefg' for i in range(len(l)/2+1, len(l)+1): __result = [] __while i: ____result.append(l[i-1]) ____i /= 2 __result.reverse() __print ''.join(result) |
9
woai110120130 OP @binux 你这个并不对 如果打乱abcdefg的顺序呢 比如插入 t c b d a f k呢
|
10
binux 2015-06-15 23:10:22 +08:00
@woai110120130 你只要求是满二叉树啊,又没规定是怎么插入的
|
11
woai110120130 OP 看看最后那段话 问题在最后
|
12
binux 2015-06-15 23:17:26 +08:00 1
@woai110120130 谁去看最后啊,那不就是个小根堆啊
|
13
Heartwork 2015-06-15 23:19:25 +08:00
|
18
zwzmzd 2015-06-15 23:29:09 +08:00
我觉得这个题目限制不严,比如说不能先排序,那如果之后的算法内比较再交换允许吗?一般的算法题,限制时间复杂度和空间复杂度,都是很明确的。
提供个思路:用一维数组表示满二叉树,你可以顺序把元素全填进去,然后快排调整 |
21
zwzmzd 2015-06-15 23:33:43 +08:00
再者,基于比较的排序算法已经证明了时间复杂度下界是O(nlogn)。你要的结果里面所有元素已经有序了,所以如果你的算法基于比较,也不可能超过这个下界。
|
25
Heartwork 2015-06-15 23:45:26 +08:00 via Android
|
26
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,不符合小根堆性质了 结论:已经调整完毕的小根堆,不可随意交换某两个孩子的位置。 |
27
Heartwork 2015-06-15 23:48:50 +08:00 via Android
有序的完全二叉树为一有序序列,在插入过程中插入位置之后的节点都需要向后移动,所以这个题目等同于求一个有序数组的插入算法…
这样应该没问题了。 |
28
woai110120130 OP @zwzmzd 其实说不能先排序 是考虑到性能的问题 每次都要排序 会浪费极大的性能 其实这也不是真实中需要的算法了 只不过是在做题的过程中产生的思考罢了 看了楼上的 觉得还没有满意的答案 为什么没有人动手实现一下呢 想的永远回比做起来简单
|
29
woai110120130 OP @Heartwork bingo 其实这么做 把先排序换成了后排序 我在想有没有更好的办法
|
30
Heartwork 2015-06-16 00:03:31 +08:00 via Android
后排序会导致插入过程中树无法保持有序的条件,这个题目就退化为给一个数组排序了。
底层如果使用二叉树的话,需要维护每一个元素的“前驱”和“后继”,前驱和后继指value的前一个和后一个。 这样插入时需要遍历插入位置之后的元素,复杂度和数组的相同。 |
32
woai110120130 OP @Heartwork 洗澡的时候想了想 这并没有什么卵用 排完序之后 还需要重新组织二叉树 还是违背题的
|
34
woai110120130 OP @Heartwork 亲 你觉得可行 可以写出来让大家学习学习
|
35
Heartwork 2015-06-16 00:09:54 +08:00 via Android
@woai110120130
所以底层用数组就行了 |
36
binux 2015-06-16 00:39:02 +08:00
@Heartwork
1、如果这么理解,这个题目是有问题的。 既然第 n 层 全部大于 第 n-1 层,「右孩子都大于左孩子」没有任何意义,在同一层之间交换元素,没有任何影响和副作用。那么这个 「右孩子都大于左孩子」的要求,随便交换一下元素就可以了。 2、其次,这个问题不是完全排序的。 只要使用快速划分,让数组左边一半小于右边一半,然后对左边继续前面的过程。再加上1所诉的的交换元素,就可以建立起符合要求的树了。复杂度只有 O(n) |
37
woai110120130 OP 楼上的诸位说这么多只不过是纸上谈兵罢了 没有一个肯做出来用事实说话
|
38
Heartwork 2015-06-16 08:45:08 +08:00 via Android
|
40
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 |
42
binux 2015-06-16 09:17:43 +08:00
|
45
zwzmzd 2015-06-16 10:17:43 +08:00 via Android
这个题目根据描述很可能有歧义,我觉得楼主你在叫人写代码之前应该给出几个测试用例,这样别人才好着手去写
|
46
woai110120130 OP @zwzmzd 哈哈 没有其他的意思 就是讨论学习 我并没有测试用例 确实有人理解的不太正确 嗯等晚上下班在写吧
|
47
woai110120130 OP @binux 不是我 我出题的意思是
隐藏 感谢回复者 Reply 40 binux 3 小时 0 分钟前 @woai110120130 事实?你自己问题都说不清楚,让人家找事实?你写得出测试用例吗? @Heartwork 不是的 a b c d e f g 成立 a b c e g d f 这个不成立 右边的都要大于左边的 可能是我描述的不清楚 实在不好意思哈 |
48
binux 2015-06-16 12:33:48 +08:00
@woai110120130 如果右边的都要大于左边,这棵树可以被证明是完全排序的,这个题目就更没意义了。
|
49
billwsy 2015-06-16 14:43:42 +08:00
你要求的所谓树用数组来表示那就是有序数组嘛,要求可以快速随机访问插入那就是块状链表了,效率是sqrt(n)
|
50
woai110120130 OP @billwsy 其实更像是杨辉三角 但是要求动态插入 而不是排好序再排列
|
51
billwsy 2015-06-16 14:52:26 +08:00
Oops, 似乎弄错了,我把条件加强了。。
|
52
billwsy 2015-06-16 15:02:59 +08:00
这样做如何:每一层对应一个大根堆,插入时二分查找到需要插入的层,O(lg lg n),将其根剔除并插入元素,将其根插入下一层,每次执行O(lg n),最多执行lg n次,效率O(lg^2 n);总效率O(lg lg n + lg n * lg n) = O(lg^2 n)。如果用数组来存储堆,并且将所有数组头尾相接起来,可以以大数组来解释二叉树。
这样的话,总效率O(n lg^2 n),缺点是插入时会破坏所有原有的父子关系。 |
53
billwsy 2015-06-16 15:05:52 +08:00
Oops,又漏了。用大数组来解释时,会出现左儿子大于右儿子的情况,访问时交换它们修正就可以了
|
55
billwsy 2015-06-16 15:10:45 +08:00
好吧,按@woai110120130 47楼的解释,那我的解答就是49楼提到的块状链表了……
洗洗睡了…… |
56
woai110120130 OP @billwsy 好的吧
|