05 August 2008
Convert a Binary Search Tree to a sorted Circular Doubly-Linked List in place.
You can think of the left and right pointers as synonymous to the predecessor and successor pointers in a doubly-linked list. For a circular doubly linked list, the predecessor of the first element is the last element, and the successor of the last element is the first element.
We want to do the transformation in place. After the transformation, the left pointer of the tree node should point to its predecessor, and the right pointer should point to its successor. You should return the pointer to the smallest element of the linked list.
Example 1:
1
2
3
4
5
6
7
Input: root = [4,2,5,1,3]
Output: [1,2,3,4,5]
Explanation: The figure below shows the transformed BST. The solid line indicates the successor relationship, while the dashed line means the predecessor relationship.
Example 2:
1
2
Input: root = [2,1,3]
Output: [1,2,3]
Example 3:
1
2
3
Input: root = []
Output: []
Explanation: Input is an empty tree. Output is also an empty Linked List.
Example 4:
1
2
Input: root = [1]
Output: [1]
Constraints:
这个题要求将一个 二叉搜索树 就地转化为一个已排序好的双向循环链表 。对于双向循环列表,可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。需要返回链表中最小元素的指针。
复习一下树的遍历方式:
总的来说,有两种遍历树的策略:
下图表示了不同策略下的访问顺序,用 1-2-3-4-5 的顺序来比较不同的策略。
按照题意,利用DFS的中序遍历+备忘录。
标准的中序遍历采用 左 -> 根 -> 右 的顺序,其中 左 和 右 的部分调用递归。 本题的处理在于将前一个结点与当前结点链接,因此,必须跟踪最后一个结点,该结点在新的双向链表中是当前最大的。
同时,也需要保留第一个,也就是最小的结点,以完成闭环。 具体算法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
// 最小的(第一个)和最大的(最后一个)节点
Node first = null;
Node last = null;
public Node treeToDoublyList(Node root) {
if (root == null) {
return null;
}
inOrder(root);
// close DLL
last.right = first;
first.left = last;
return first; // 返回最小值
}
public void inOrder(Node node) {
if (node != null) { //开始中序遍历
// left
inOrder(node.left);
// node
if (last != null) {
// link the previous node (last) with the current one (node)
last.right = node;
node.left = last;
} else {
// keep the smallest node to close DLL later on
first = node;
}
last = node;
// right
inOrder(node.right);
}
}
}