这是我最近在接受采访时提出的一个问题。给出二叉树,其条件是每个左子项比根小1,右子项大1。这是一个示例树
以O(1)和O(n)时间复杂度对其进行排序。
以下是我建议的方法:
你的方法是什么?
答案 0 :(得分:2)
<强>分析强>
鉴于您对二叉树的定义,我们有以下内容,
每个节点都有父,L子和R子..其中:
L < N
R > N
P > N
我们也可以这样做:
L < N AND R > N => L < N < R => L < R
L < N AND P > N => L < N < P => L < P
R > N AND P > N => N < MIN(P,R)
N < MIN(P,R) AND L < N => L < N < MIN(P,R)
现在让我们尝试扩展它,N.L = Left-child of N
:
N.L < N
N.R > N
N.P > N
N.L.L < N.L < MIN(N, N.L.R)
N.L.R > N.L > N.L.L
N.R.L < N.R < MIN(N, N.R.R)
N.R.R > N.R > N.R.L
IF N IS N.P LEFT-CHILD: N < N.P < MIN(N.P.P, N.P.R)
IF N IS N.P RIGHT-CHILD: N > N.P.R
提议的解决方案
这个问题似乎很复杂,但我的解决方案是在遍历顺序中插入值后使用合并排序Left-Right-Parent将帮助合并排序在平均和最佳情况之间获得时间复杂度,但是使用我上面做过的比较的小技巧。
首先,我们使用Left-Right-Parent遍历收集列表中的树节点,给定以下事实:N.L < N < MIN(N.R, N.P)
并给予父级更高的权重,假设O(N.R) <= O(N.P)
,当我们的值线性减小时每次都在左侧.. > N.R.R > N.R > N > N.L > N.L.L > ..
。
以遍历顺序收集树节点后,列表中有一些已排序的块,这将有助于我们接下来要使用的合并排序。
此解决方案适用于:Time = O(n log n + n)
,Space = O(n)
这是用Java (未测试)编写的算法:
private class Node Comparable<Node>
{
public Node R;
public Node L;
public int value;
public Node (Node L, int val, Node R)
{
this.L = L;
this.value = val;
this.R = R;
}
@Override
public int compareTo(Node other)
{
return ((other != null) ? (this.value-other.value) : 0);
}
}
class Main
{
private static Node head;
private static void recursive_collect (Node n, ArrayList<Node> list)
{
if (n == null) return;
if (n.left != null) recursive_collect (n.L, list);
if (n.right != null) recursive_collect (n.R, list);
list.add(n.value);
}
public static ArrayList<Node> collect ()
{
ArrayList<Node> list = new ArrayList<Node>();
recursive_collect (head, list);
return list;
}
// sorting the tree: O(n log n + n)
public static ArrayList<Node> sortTree ()
{
// Collecting nodes: O(n)
ArrayList<Node> list = collect();
// Merge Sort: O(n log n)
Collections.sort(list);
return list;
}
// The example in the picture you provided
public static void createTestTree ()
{
Node left1 = new Node (new Node(null,-2,null), -1, new Node(null,0,null));
Node left2 = new Node (new Node(null,-1,null), 0, new Node(null,1,null));
Node right = new Node (left2, 1, new Node(null,2,null));
head = new Node (left1, 0, right);
}
// test
public static void main(String [] args)
{
createTestTree ();
ArrayList<Node> list = sortTree ();
for (Node n : list)
{
System.out.println(n.value);
}
}
}
答案 1 :(得分:1)
将给定树的一些Leaf节点修复为NewHead。
编写函数Pop()从给定树中删除一些节点..!
编写pop节点,只有当它被删除时才会将其删除!等于NewHead。
从树中获取pop值,将其插入New binary搜索树,New Head as Head节点。
所以你将从树中删除一个元素,将它添加到新的搜索树中。
直到树头指向NewHead。
因此,所有元素现在都在二叉搜索树中,指向New head,它将是
显然按排序顺序。
这种方式可以保证你在O(NlogN)中进行排序。
答案 2 :(得分:1)
我想,你正在寻找DFS(深度优先搜索)。 在深度优先搜索中,想法是在回溯之前尽可能地从邻居到邻居旅行。决定可能深度的原因是你必须跟随边缘,而不是两次访问任何顶点。
提升已经提供了它:请参阅here
答案 3 :(得分:0)
使用快速排序。
节点在多个阵列中以最低级别排序&amp;这些排序元素数组最后合并。
E.g。
功能quick_sort(节点n)
1.转到左侧模式,如果不为空,则调用quick_sort。
2.转到右边的元素,如果不为null,则调用quick_sort。
3.合并左节点排序的结果&amp;右节点排序&amp;当前节点
4.返回合并数组。
答案 4 :(得分:-1)
我没有得到这个问题。二叉树是否已经排序?如果您想按顺序打印出项目(或按顺序访问它们),此代码将起作用
/**
* Show the contents of the BST in order
*/
public void show () {
show(root);
System.out.println();
}
private static void show(TreeNode node) {
if (node == null) return;
show(node.lchild);
System.out.print(node.datum + " ");
show(node.rchild);
}
我相信这会是o(n)复杂性。要返回列表而不是打印,只需创建一个并通过将子项添加到列表
来替换每个show语句