leetcode114 二叉树展开为链表
题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 给定一个二叉树,原地将它展开为一个单链表。
例如,给定二叉树
1 / \ 2 5 / \ \ 3 4 6 将其展开为:
1 \ 2 \ 3 \ 4 \ 5 \ 6
|
思路:
一开始最初的想法就是遍历一次二叉树,然后把节点依次存入到一个新的链表中。后来写完后发现题目说的是原地展开为一个单链表,那么就是不能创建空间复杂度是大于O(1)的数据结构了(原地算法要求引入的数据结构是常量级别的)。
方法一:
最开始的想法引入了O(n)的栈用来前序遍历二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public void flatten(TreeNode root) { List<TreeNode> result = new LinkedList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode currNode = root; while(currNode != null ||!stack.isEmpty()) { while (currNode != null) { result.add(currNode); stack.push(currNode); currNode = currNode.left; } currNode = stack.pop(); currNode = currNode.right; }
for (int i = 1; i < result.size(); i++) { TreeNode frontNode = result.get(i - 1); TreeNode curr = result.get(i); // 变成单链表 左子树都是null frontNode.left = null; frontNode.right = curr; } }
|
时间复杂度:O(n)
空间复杂度:O(n)
方法二:
使用了常量级的参数来实现了新的算法,方式非常的巧妙。我没想出来,也是看了题解之后才想明白。
看下图帮助理解一下:
如果一个节点的左子树是空的,那么对于这个节点,直接就是符合单链表的结构。
如果一个节点的左子树不是空的,假设节点是1,那么左子树的最后一个节点4,变成单链表后,该节点1的右子树,5->6是挂在4下面的。
因此只要找到左子树中的最后一个节点,把右子树挂在左子树最后一个节点上就可以了,然后将节点1的左子树置为null。再节点往下走,不断的重复该步骤即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public void flatten2(TreeNode root) { while (root != null) { // 节点的左子树不为null if (root.left != null) { TreeNode left = root.left; TreeNode temp = left; // 找到左子树的最后一个元素 while (temp.right != null) { temp = temp.right; } temp.right = root.right; root.left = null; root.right = left; } // 左子树为null 直接把右子树挂在当前节点上 root = root.right; } }
|
时间复杂度:O(n)
空间复杂度:O(1)