|
| 1 | +""" |
| 2 | +Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. |
| 3 | +
|
| 4 | +For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. |
| 5 | +
|
| 6 | +Example: |
| 7 | +
|
| 8 | +Given the sorted linked list: [-10,-3,0,5,9], |
| 9 | +
|
| 10 | +One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: |
| 11 | +
|
| 12 | + 0 |
| 13 | + / \ |
| 14 | + -3 9 |
| 15 | + / / |
| 16 | + -10 5 |
| 17 | +
|
| 18 | +
|
| 19 | + 这次给的是一个排序过的链表,链表和数组有所不同,链表的话无法使用索引,或者说使用索引所需要的时间是 O(n) 并非 O(1)。 |
| 20 | + 当然可以把链表转换成一个数组然后按照数组的方法去解,这样不会出错,时间复杂度上也是同样的,就是空间复杂度上要高一些。 |
| 21 | + |
| 22 | + 我自己的话没想到其他的思路: |
| 23 | + 在Discuss里看到一个 Java 的思路,觉得非常棒: |
| 24 | +
|
| 25 | + 前面我们分析过这其实就是个中序遍历的结果,按照这个思路,如果能按照中序遍历逆推回去,即可得到一颗完整的高度平衡的二叉搜索树。 |
| 26 | +
|
| 27 | + 这个思路也是这样的,在做二叉树的中序遍历时用递归一般这样写: |
| 28 | + ``` |
| 29 | + if root.left: |
| 30 | + recursive(root.left) |
| 31 | + root.val |
| 32 | + if root.right: |
| 33 | + recursive(root.right) |
| 34 | + |
| 35 | + ``` |
| 36 | + 如果我们能找到left的头,并一直持续到right的尾,即可得到一颗二叉搜索树,这棵树可能并不会与原来的相同。 |
| 37 | +
|
| 38 | + 如: |
| 39 | + 中序结果是: |
| 40 | + [-1, 1, 2, 3] |
| 41 | + 这颗树可能是: |
| 42 | + 1 |
| 43 | + / \ |
| 44 | + -1 2 |
| 45 | + \ |
| 46 | + 3 |
| 47 | +
|
| 48 | +也可以是: |
| 49 | + 2 |
| 50 | + / \ |
| 51 | + 1 3 |
| 52 | + / |
| 53 | +-1 |
| 54 | + 那就按原来的数组中的方法: |
| 55 | + 如果要从中序遍历的结果生成二叉树,首先需要获取的是 mid 中位,找到它的根。剩下的也是不断找到根。 |
| 56 | + [-10,-3,0,5,9] |
| 57 | + 1. 第一步先找一下链表的长度。 |
| 58 | + 2. 第二步则给函数说左有几个,右有几个。 |
| 59 | + |
| 60 | + 左边有几个的话很简单: |
| 61 | + 直接 length // 2即可,地板除的话会舍弃。 比如如果有4个数据。 4//2之后左边的还剩下 两个 [0,1] |
| 62 | +
|
| 63 | + 右边的话: |
| 64 | + 需要原来的长度 减去左边的长度 再减去 这个的根得知。 |
| 65 | +
|
| 66 | + 这样不断递归至 size 为 0 即为左子树的头,与右子树的尾。 |
| 67 | + [-10,-3,0,5,9] |
| 68 | +
|
| 69 | + 1. size = 5 |
| 70 | + left = 5//2 = 2 [-10,-3] |
| 71 | + right = 5 - left - 1 = 5 - 2 - 1 = 2 [5, 9] |
| 72 | +
|
| 73 | + 2. size = 1.left = 2 |
| 74 | + left = 2//1 = 1 [-10] |
| 75 | + right = 2 - left - 1 = 2 - 1 -1 = 0 [] |
| 76 | +
|
| 77 | + 3. size = 2.left = 1 |
| 78 | + left = 1 // 2 = 0 |
| 79 | + right = 1 - 0 - 1 = 0 |
| 80 | + 这一步开始返回链表的第一个值 -10 作为 2 里左节点的val.之后返回到2 |
| 81 | + 2. 则把自己的节点值覆盖为链表中下一个值 -3。 之后返回到1. |
| 82 | + 1. 则把自己的节点值覆盖为链表中的下一个值 0。 之后开始right的递归。同样的操作。 |
| 83 | + --- |
| 84 | + 4. size = 1.right = 2 |
| 85 | + left = 2//1 = 1 [5] |
| 86 | + right = 2 - left - 1 = 2 -1 -1 =0 [] |
| 87 | + 5. size = 4.left = 1 |
| 88 | + left = 1 // 2 = 0 [] |
| 89 | + right = 1- 0 -1 = 0 [] |
| 90 | + ... |
| 91 | +
|
| 92 | +关键词: |
| 93 | +中序遍历,左右子树节点的个数。 |
| 94 | +
|
| 95 | +beat 99% |
| 96 | +
|
| 97 | +测试地址: |
| 98 | +https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/description/ |
| 99 | +
|
| 100 | +""" |
| 101 | +# Definition for singly-linked list. |
| 102 | +# class ListNode(object): |
| 103 | +# def __init__(self, x): |
| 104 | +# self.val = x |
| 105 | +# self.next = None |
| 106 | + |
| 107 | +# Definition for a binary tree node. |
| 108 | +# class TreeNode(object): |
| 109 | +# def __init__(self, x): |
| 110 | +# self.val = x |
| 111 | +# self.left = None |
| 112 | +# self.right = None |
| 113 | + |
| 114 | +class Solution(object): |
| 115 | + def sortedListToBST(self, head): |
| 116 | + """ |
| 117 | + :type head: ListNode |
| 118 | + :rtype: TreeNode |
| 119 | + """ |
| 120 | + size = 0 |
| 121 | + |
| 122 | + self.c_head = head |
| 123 | + |
| 124 | + while head: |
| 125 | + size += 1 |
| 126 | + head = head.next |
| 127 | + |
| 128 | + def makeBSTByInorder(size): |
| 129 | + if not size: |
| 130 | + return |
| 131 | + |
| 132 | + root = TreeNode(None) |
| 133 | + |
| 134 | + root.left = makeBSTByInorder(size//2) |
| 135 | + root.val = self.c_head.val |
| 136 | + self.c_head = self.c_head.next |
| 137 | + root.right = makeBSTByInorder(size-size//2-1) |
| 138 | + |
| 139 | + return root |
| 140 | + |
| 141 | + return makeBSTByInorder(size) |
0 commit comments