给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵
平衡
二叉搜索树。
示例 1:
1 2 3 输入:nums = [-10 ,-3 ,0,5,9] 输出:[0,-3 ,9,-10 ,null,5] 解释:[0,-10 ,5,null,-3 ,null,9] 也将被视为正确答案:
示例 2:
1 2 3 输入:nums = 输出: 解释: 和 都是高度平衡二叉搜索树。
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
按 严格递增 顺序排列
思路 这里需要回顾下我们之前看过的二叉搜索树的概念,详细请见leetcode刷题记录——二叉搜索树
然后借助我们的概念,root节点就是整个nums的中间位置,然后递归就可以了。
代码 1 2 3 4 5 6 7 8 9 class Solution : def sortedArrayToBST (self, nums: List [int ] ) -> Optional [TreeNode]: if not nums: return None mid = len (nums) // 2 root = TreeNode(nums[mid]) root.left = self .sortedArrayToBST(nums[:mid]) root.right = self .sortedArrayToBST(nums[mid+1 :]) return root
时间复杂度 时间复杂度O(n),空间复杂度O(log n),执行时间43ms,消耗内存17.7MB
148 排序链表 Medium 给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
1 2 输入:head = [4,2,1,3 ] 输出:[1,2,3,4 ]
示例 2:
1 2 输入:head = [-1,5,3,4 ,0 ] 输出:[-1,0,3,4 ,5 ]
示例 3:
提示:
链表中节点的数目在范围 [0, 5 * 104]
内
-105 <= Node.val <= 105
思路 首先需要明确的一点是我们需要用到两个方法,一个将链表拆分为两部分,一个用来合并链表
拆分部分需要用到快慢指针,合并部分需要用到虚拟节点和尾节点
其余直接看代码,写了注释
代码 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 class Solution : def sortList (self, head: Optional [ListNode] ) -> Optional [ListNode]: if not head or not head.next : return head slow, fast = head, head.next while fast and fast.next : slow = slow.next fast = fast.next .next second = slow.next slow.next = None left = self .sortList(head) right = self .sortList(second) return self .merge(left, right) def merge (self, left, right ): dummy = tail = ListNode(0 ) while left and right: if left.val < right.val: tail.next = left left = left.next else : tail.next = right right = right.next tail = tail.next tail.next = left if left else right return dummy.next
时间复杂度 时间复杂度O(nlog n),空间复杂度O(log n),执行时间294ms,消耗内存31.4MB
427 建立四叉树 Medium 给你一个 n * n
矩阵 grid
,矩阵由若干 0
和 1
组成。请你用四叉树表示该矩阵 grid
。
你需要返回能表示矩阵 grid
的 四叉树 的根结点。
四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性:
val
:储存叶子结点所代表的区域的值。1 对应 True ,0 对应 False 。注意,当 isLeaf
为 False 时,你可以把 True 或者 False 赋值给节点,两种值都会被判题机制 接受 。
isLeaf
: 当这个节点是一个叶子结点时为 True ,如果它有 4 个子节点则为 False 。
1 2 3 4 5 6 7 8 class Node { public boolean val; public boolean isLeaf; public Node topLeft ; public Node topRight ; public Node bottomLeft ; public Node bottomRight ; }
我们可以按以下步骤为二维区域构建四叉树:
如果当前网格的值相同(即,全为 0
或者全为 1
),将 isLeaf
设为 True ,将 val
设为网格相应的值,并将四个子节点都设为 Null 然后停止。
如果当前网格的值不同,将 isLeaf
设为 False, 将 val
设为任意值,然后如下图所示,将当前网格划分为四个子网格。
使用适当的子网格递归每个子节点。
如果你想了解更多关于四叉树的内容,可以参考 wiki 。
四叉树格式:
你不需要阅读本节来解决这个问题。只有当你想了解输出格式时才会这样做。输出为使用层序遍历后四叉树的序列化形式,其中 null
表示路径终止符,其下面不存在节点。
它与二叉树的序列化非常相似。唯一的区别是节点以列表形式表示 [isLeaf, val]
。
如果 isLeaf
或者 val
的值为 True ,则表示它在列表 [isLeaf, val]
中的值为 1 ;如果 isLeaf
或者 val
的值为 False ,则表示值为 0 。
示例 1:
1 2 3 4 输入:grid = [[0,1],[1,0]] 输出:[[0,1],[1,0],[1,1],[1,1],[1,0]] 解释:此示例的解释如下: 请注意,在下面四叉树的图示中,0 表示 false ,1 表示 True 。
示例 2:
1 2 3 4 5 6 输入:grid = 输出: 解释:网格中的所有值都不相同。我们将网格划分为四个子网格。 topLeft,bottomLeft 和 bottomRight 均具有相同的值。 topRight 具有不同的值,因此我们将其再分为 4 个子网格,这样每个子网格都具有相同的值。 解释如下图所示:
提示:
n == grid.length == grid[i].length
n == 2x
其中 0 <= x <= 6
思路 主要用到两个函数,same
和dfs
。same
函数用于检查二维数组中所有元素是否相同,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 class Solution : def construct (self, grid: List [List [int ]] ) -> 'Node' : def same (a, b, c, d ): cur = grid[a][c] for i in range (a, b): for j in range (c, d): if grid[i][j] != cur: return False return True def dfs (rs, re, ls, le ): if same(rs, re, ls, le): node = Node(grid[rs][ls], True , None , None , None , None ) else : node = Node(grid[rs][ls], False , None , None , None , None ) row_middle = (rs + re) // 2 col_middle = (ls + le) // 2 node.topLeft = dfs(rs, row_middle, ls, col_middle) node.topRight = dfs(rs, row_middle, col_middle, le) node.bottomLeft = dfs(row_middle, re, ls, col_middle) node.bottomRight = dfs(row_middle, re, col_middle, le) return node l = len (grid) return dfs(0 , l, 0 , l)
时间复杂度 时间复杂度$O(n^2logn)$,空间复杂度$O(logn)$,执行时间89ms,消耗内存17.35MB
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
1 2 3 4 5 6 7 8 9 10 输入:lists = [[1 ,4 ,5 ],[1 ,3 ,4 ],[2 ,6 ]] 输出:[1 ,1 ,2 ,3 ,4 ,4 ,5 ,6 ] 解释:链表数组如下: [ 1 ->4 ->5 , 1 ->3 ->4 , 2 ->6 ] 将它们合并到一个有序链表中得到。1 ->1 ->2 ->3 ->4 ->4 ->5 ->6
示例 2:
示例 3:
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
按 升序 排列
lists[i].length
的总和不超过 10^4
思路 整体思路上借助最小堆的特性来做,堆中的元素需要包含节点的值,节点的唯一标识,节点本身
关于最小堆的特性:
最小堆是一种完全二叉树,这意味着除了最后一层外,其他层都是满的,并且最后一层的节点都尽量靠左排列。
对于任意节点 i
,其左子节点 2*i + 1
和右子节点 2*i + 2
的值都大于或等于节点 i
的值。
代码 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 class Solution : def mergeKLists (self, lists: List [Optional [ListNode]] ) -> Optional [ListNode]: dummy = ListNode(0 ) p = dummy pq = [] for head in lists: if head: heapq.heappush(pq, (head.val, id (head), head)) while pq: node = heapq.heappop(pq)[2 ] p.next = node if node.next : heapq.heappush(pq, (node.next .val, id (node.next ), node.next )) p = p.next return dummy.next
时间复杂度 时间复杂度$O(nlogk)$,空间复杂度O(n + k),执行时间49ms,消耗内存18.8MB