leetcode刷題筆記一百一十六題與一百一十七題 填充每個節點的下一個右側節點指標 與 填充每個節點的下一個右側節點指標 II
leetcode刷題筆記一百一十六題與一百一十七題 填充每個節點的下一個右側節點指標 與 填充每個節點的下一個右側節點指標 II
問題描述:
116題問題描述
給定一個完美二叉樹,其所有葉子節點都在同一層,每個父節點都有兩個子節點。二叉樹定義如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每個 next 指標,讓這個指標指向其下一個右側節點。如果找不到下一個右側節點,則將 next 指標設定為 NULL。初始狀態下,所有 next 指標都被設定為 NULL。
輸入:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}
輸出:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1}
解釋:給定二叉樹如圖 A 所示,你的函式應該填充它的每個 next 指標,以指向其下一個右側節點,如圖 B 所示。
117題問題描述
給定一個二叉樹
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每個 next 指標,讓這個指標指向其下一個右側節點。如果找不到下一個右側節點,則將 next 指標設定為 NULL。初始狀態下,所有 next 指標都被設定為 NULL。
進階:
你只能使用常量級額外空間。
使用遞迴解題也符合要求,本題中遞迴程式佔用的棧空間不算做額外的空間複雜度。輸入:root = [1,2,3,4,5,null,7]
輸出:[1,#,2,3,#,4,5,7,#]
解釋:給定二叉樹如圖 A 所示,你的函式應該填充它的每個 next 指標,以指向其下一個右側節點,如圖 B 所示。提示:
樹中的節點數小於 6000
-100 <= node.val <= 100
/**
* 116題與117題的主要區別在於116題的樹是完美二叉樹,117題的樹是普通二叉樹,處理這類題的思想基本是一致的。1.採用層次遍歷,遍歷過程中修改next指標,或者在上一層遍歷時建立下一層的next指標關係,逐層解決
*/
//基於層次遍歷的解法
/**
* Definition for a Node.
* class Node(var _value: Int) {
* var value: Int = _value
* var left: Node = null
* var right: Node = null
* var next: Node = null
* }
*/
import scala.collection.mutable
object Solution {
def connect(root: Node): Node = {
if (root == null) return root
val queue = mutable.Queue[Node]()
queue.enqueue(root)
while (queue.isEmpty == false){
val queueSize = queue.size
//到本次倒數第二個結點,全部更新next指標
for (i <- 0 to queueSize-2){
val currNode = queue.dequeue
val nextNode = queue.head
currNode.next = nextNode
//排除非空的情況
if (currNode.left != null) queue.enqueue(currNode.left)
if (currNode.right != null) queue.enqueue(currNode.right)
}
//更新最後一個結點的next指標與入隊情況
val floorLastNode = queue.dequeue
floorLastNode.next = null
if (floorLastNode.left != null) queue.enqueue(floorLastNode.left)
if (floorLastNode.right != null) queue.enqueue(floorLastNode.right)
}
return root
}
}
//使用已建立的 next 指標方法,本質上利用上層遍歷更新下層的next指標
//116題
/**
* Definition for a Node.
* class Node(var _value: Int) {
* var value: Int = _value
* var left: Node = null
* var right: Node = null
* var next: Node = null
* }
*/
object Solution {
def connect(root: Node): Node = {
if (root == null) return root
//始終從每層的左側結點開始
var leftMost = root
while (leftMost.left != null){
//使用head遍歷整層結點
var head = leftMost
while (head != null){
//由於是完美二叉樹,head不為空,將左兒子的next指向右兒子
head.left.next = head.right
//不同父節點的相鄰節點,將右子樹的next指向存在的兄弟節點的左兒子
if (head.next != null) head.right.next = head.next.left
//更新head結點
head = head.next
}
leftMost = leftMost.left
}
return root
}
}
//117題
object Solution {
def connect(root: Node): Node = {
var parent = root
val head = new Node(0)
while (parent != null){
//當前層
var curr = head
while (parent != null){
//檢查左子樹情況,有就更新next
if (parent.left != null){
curr.next = parent.left
curr = curr.next
}
//檢查左子樹情況,有就更新next
if (parent.right != null){
curr.next = parent.right
curr = curr.next
}
//層內更新
parent = parent.next
}
//前往下一層
parent = head.next
head.next = null
}
return root
}
}