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:
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:
Input: root = [2,1,3] Output: [1,2,3]
Constraints:
- The number of nodes in the tree is in the range
[0, 2000]
. -1000 <= Node.val <= 1000
- All the values of the tree are unique.
题目要求把一棵二叉搜索树转换成一个循环双向链表。具体要求是一个节点的左指针left指向其前继(predecessor), 右指针right指向后继(successor)。最后头节点的left指向尾节点,尾节点的right指向头节点。如果熟悉前继和后继的概念就会知道最后链表是排好序递增的,其实就是二叉搜索树的中序遍历的顺序。很显然又是可以用递归法或迭代法。
递归法,中序遍历的顺序是,先左子树,再根节点,最后右子树。如果把左子树和右子树分别转换成两个双向链表,那把左子树链表与根节点相连,再与右子树链表相连,就形成了一个完整的双向链表,最后再把首尾相连就形成了循环双向链表。每棵子树都可以被当成一棵新树来处理,转换方式都一样,因此可递归调用处理,递归的终止条件是树的节点数小于等于1。由于最后需要首尾相连,需要定义两个指针一个指向头节点,一个指向尾节点,再递归调用处理每个子树时,需要实时更新尾指针,整棵树处理完了,两个指针指向的就是完整链表的头和尾。
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return None
def helper(node):
if not node :
return
nonlocal head, tail
helper(node.left)
if tail:
tail.right = node
node.left = tail
else:
head = node
tail = node
helper(node.right)
head, tail = None, None
helper(root)
tail.right = head
head.left = tail
return head
迭代法:就是按照二叉搜索树的中序遍历的迭代算法来挨个处理每个节点,用一个头指针head指向迭代开始的第一个节点(就是链表的头节点),再用一个尾指针tail实时指向中序遍历过程中当前节点cur的前一个节点(链表的尾节点),每次从堆栈中取出当前节点cur,再处理当前节点与前一个节点(链表的尾节点)的链接关系:tail.right = cur, cur.left = tail。还需判断当前是否存在右子树,如存在需要把右子树相关节点放入堆栈。
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return None
head,tail = None,None
st = []
cur = root
while cur:
st.append(cur)
cur = cur.left
while st:
cur = st.pop()
if not head:
head = cur
tail = cur
else:
tail.right = cur
cur.left = tail
tail = tail.right
if cur.right:
tmp = cur.right
while tmp:
st.append(tmp)
tmp = tmp.left
tail.right = head
head.left = tail
return head