面试题36 二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
题解
题目要求排序的双向链表,则:
- 采用中序遍历,刚好节点的值为一个递增的序列。
- 双向链表: 则链表中相邻的两个节点之间(如果驱节点 pre ,当前节点 cur)有则 pre.right = cur, cur.left = pre
算法流程
采用非递归的中序dfs,用一个栈记录访问次序,一个辅助链表记录访问结果,在辅助链表中修改指针指向。返回辅助链表的第一个节点;
复杂度分析:
时间复杂度 O(N) : N 为二叉树的节点数,中序遍历需要访问所有节点。
空间复杂度 O(N) : 辅助链表res使用 O(N)空间。辅助栈stack最差情况下也是O(N)空间。
import java.util.ArrayList; import java.util.Stack; public class Solution { public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree == null) return null; if(pRootOfTree.left == null && pRootOfTree.right == null) return pRootOfTree; ArrayList<TreeNode> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode temp = pRootOfTree; // 形成一个中序遍历的结果,并添加指针。 while(!stack.empty() || temp != null){ if(temp != null){ stack.add(temp); temp = temp.left; }else{ temp = stack.pop(); res.add(temp); temp = temp.right; } } // 修改链表指针指向。 for(int i = 0; i < res.size()-1; i++){ res.get(i+1).left = res.get(i); res.get(i).right = res.get(i+1); } return res.get(0); } }
递归写法:
时间复杂度 O(N) : N 为二叉树的节点数,中序遍历需要访问所有节点。
空间复杂度 O(N) : 当二叉树退化为链表时,递归辅助栈最差情况下也是O(N)空间。
public class Solution { TreeNode head = null; TreeNode pre = null; public TreeNode Convert(TreeNode pRootOfTree) { dfs(pRootOfTree); return head; } void dfs(TreeNode cur){ if(cur == null) return ; dfs(cur.left); if(pre != null) pre.right = cur; // 一般情况 else head = cur; cur.left = pre; pre = cur; dfs(cur.right); } }