คลาส TreeNode และ BFS แบบเรียงตามระดับ
สร้างต้นไม้ทวิภาคจากอาร์เรย์ สร้าง BFS ด้วย deque เพื่อพิมพ์ทีละระดับ และแก้โจทย์ความลึกสูงสุดด้วย BFS
คลาส TreeNode และ BFS แบบเรียงตามระดับ เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
พื้นฐานของคลาส TreeNode
ต้นไม้ทวิภาคคือโครงสร้างข้อมูลแบบลำดับชั้นที่แต่ละโหนดมีลูกได้ไม่เกินสองโหนด เรียกว่า ซ้าย และ ขวา ในไพธอน เราจำลองโหนดด้วยคลาสง่าย ๆ: class TreeNode: def __init__(self, val=0, left=None, right=None) ปัญหาต้นไม้ทุกข้อในการสัมภาษณ์เริ่มต้นจากคำจำกัดความนี้ — คุณจะพบคำจำกัดความนี้ในโค้ดโครงของปัญหาต้นไม้บน LeetCode แทบทุกข้อ
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# Build a small tree manually:
# 1
# / \
# 2 3
# / \
# 4 5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(root.val, root.left.val, root.right.val)การสร้างต้นไม้จากอาร์เรย์
โจทย์สัมภาษณ์มักให้อาร์เรย์ตามระดับที่ใช้แทนต้นไม้ โดย None ใช้ระบุโหนดที่หายไป เมื่อกำหนดดัชนี i ลูกด้านซ้ายจะอยู่ที่ 2i+1 และลูกด้านขวาจะอยู่ที่ 2i+2 การเขียนตัวช่วยเพื่อแปลงอาร์เรย์นี้กลับเป็น TreeNodes ที่เชื่อมโยงกันเป็นเครื่องมือที่มีประโยชน์และช่วยประหยัดเวลาในช่วงฝึกฝน
from collections import deque
def build_tree(arr):
if not arr or arr[0] is None:
return None
root = TreeNode(arr[0])
q = deque([root])
i = 1
while q and i < len(arr):
node = q.popleft()
if i < len(arr) and arr[i] is not None:
node.left = TreeNode(arr[i])
q.append(node.left)
i += 1
if i < len(arr) and arr[i] is not None:
node.right = TreeNode(arr[i])
q.append(node.right)
i += 1
return root
root = build_tree([1, 2, 3, 4, 5, None, 6])
print(root.val, root.left.val, root.right.val)BFS คืออะไรและเหตุใดจึงใช้คิว
การค้นหาแบบกว้าง (BFS)จะเยี่ยมชมโหนดทั้งหมดที่ความลึก d ก่อนเยี่ยมชมโหนดใด ๆ ที่ความลึก d+1 การท่องผ่านทีละระดับนี้ตรงกับสิ่งที่คิว (FIFO) มอบให้พอดี: เราใส่โหนดรากเข้าคิว จากนั้นประมวลผลโหนดทีละโหนด และใส่ลูกของแต่ละโหนดเข้าคิวไปเรื่อย ๆ เมธอด collections.deque ของไพธอนมี appendleft และ popleft ที่ใช้เวลา O(1) จึงเป็นตัวเลือกที่เหมาะสมกว่าลิสต์ธรรมดา
from collections import deque
def bfs_print(root):
if not root:
return
q = deque([root])
while q:
node = q.popleft()
print(node.val, end=' ')
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
bfs_print(root) # 1 2 3 4BFS ตามระดับ: การจัดกลุ่มตามระดับ
รูปแบบ BFS มาตรฐานจะจัดกลุ่มโหนดตามระดับด้วยการบันทึกขนาดคิวเมื่อเริ่มต้นการวนซ้ำแต่ละรอบ ประมวลผลโหนดให้ครบตามจำนวนนั้น รวบรวมค่า แล้วจึงไปยังระดับถัดไป วิธีนี้จะสร้างรายการของรายการ ซึ่งเป็นรูปแบบผลลัพธ์ที่พบบ่อยมากในการสัมภาษณ์ สำหรับปัญหาอย่าง การท่องต้นไม้ทวิภาคตามระดับ, การท่องแบบซิกแซ็ก และ มุมมองด้านขวา
from collections import deque
def level_order(root):
if not root:
return []
result = []
q = deque([root])
while q:
level_size = len(q)
level = []
for _ in range(level_size):
node = q.popleft()
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
result.append(level)
return result
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
print(level_order(root)) # [[1], [2, 3], [4]]ความลึกสูงสุดด้วย BFS
ความลึกสูงสุดของต้นไม้ทวิภาคเท่ากับจำนวนระดับในการท่องผ่านด้วย BFS เพียงนับจำนวนครั้งที่วนรอบระดับเสร็จสมบูรณ์ วิธีนี้ใช้เวลา O(n) และใช้พื้นที่ O(w) โดย w คือความกว้างสูงสุดของต้นไม้ สำหรับต้นไม้สมดุล w มีค่าเป็น O(n/2) ดังนั้นพื้นที่ในกรณีแย่ที่สุดจึงเป็น O(n)
from collections import deque
def max_depth_bfs(root):
if not root:
return 0
depth = 0
q = deque([root])
while q:
depth += 1
for _ in range(len(q)):
node = q.popleft()
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return depth
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
print(max_depth_bfs(root)) # 3มุมมองด้านขวาของต้นไม้ทวิภาค
มุมมองด้านขวาจะคืนค่าโหนดสุดท้ายที่มองเห็นเมื่อดูต้นไม้จากด้านขวา — หรือก็คือสมาชิกตัวสุดท้ายของแต่ละระดับในการท่องผ่านด้วย BFS นี่เป็นการประยุกต์ใช้ BFS ตามระดับโดยตรง: เก็บโหนดสุดท้ายในแต่ละรอบของระดับ ความซับซ้อนด้านเวลาคือ O(n) และใช้พื้นที่ O(w) สำหรับคิว
from collections import deque
def right_side_view(root):
if not root:
return []
result = []
q = deque([root])
while q:
level_size = len(q)
for i in range(level_size):
node = q.popleft()
if i == level_size - 1:
result.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return result
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.right = TreeNode(5)
print(right_side_view(root)) # [1, 3, 5]การท่องต้นไม้ตามระดับแบบซิกแซ็ก
ในการ ท่องแบบซิกแซ็ก จะเก็บระดับคี่จากซ้ายไปขวา และระดับคู่จากขวาไปซ้าย วิธีการเขียนที่เรียบง่ายที่สุดคือคงคิวของ BFS ไว้เหมือนเดิม แล้ว กลับลำดับรายการของระดับสลับกัน ก่อนเพิ่มลงในผลลัพธ์ ให้ติดตามทิศทางด้วยตัวบ่งชี้แบบบูลีนที่สลับค่าทุกระดับ วิธีนี้ช่วยหลีกเลี่ยงความซับซ้อนของคิวสองด้านในลูปด้านใน
from collections import deque
def zigzag_level_order(root):
if not root:
return []
result = []
q = deque([root])
left_to_right = True
while q:
level = []
for _ in range(len(q)):
node = q.popleft()
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
result.append(level if left_to_right else level[::-1])
left_to_right = not left_to_right
return result
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(zigzag_level_order(root))การวิเคราะห์ความซับซ้อนด้านพื้นที่ของ BFS
BFS ใช้พื้นที่ O(w) โดยที่ w คือความกว้างสูงสุดของต้นไม้ สำหรับ ต้นไม้ทวิภาคสมบูรณ์ ที่มีโหนด n โหนด ระดับสุดท้ายจะมี (n+1)/2 โหนด ดังนั้น BFS อาจเก็บโหนดในคิวพร้อมกันได้มากถึง n/2 โหนด ทำให้ BFS ใช้พื้นที่ มากกว่า DFS (O(h)) สำหรับต้นไม้สมดุลที่กว้าง แต่ใช้พื้นที่ น้อยกว่าสำหรับต้นไม้ที่เอนลึก ซึ่งความลึกของสแตกการเรียก DFS เท่ากับ n
# Space comparison: BFS vs DFS on a complete binary tree
# n=15 nodes, height=4
# BFS max queue size = 8 (last level)
# DFS max call stack = 4 (height)
# For a skewed tree (like a linked list):
# n=1000 nodes
# BFS max queue size = 1 (always 1 node per level)
# DFS max call stack = 1000 (recursion depth -> stack overflow!)
from collections import deque
def skewed_tree(n):
root = TreeNode(1)
cur = root
for i in range(2, n+1):
cur.right = TreeNode(i)
cur = cur.right
return root
root = skewed_tree(10)
print('BFS on skewed tree is safe')ค่าเฉลี่ยของแต่ละระดับในต้นไม้ทวิภาค
การคำนวณ ค่าเฉลี่ยในแต่ละระดับ เป็นการประยุกต์ใช้ BFS โดยตรงอีกรูปแบบหนึ่ง ให้รวมค่าทั้งหมดในระดับหนึ่ง หารด้วยจำนวนโหนด แล้วเพิ่มลงในรายการผลลัพธ์ โจทย์นี้ทดสอบว่าคุณสามารถคำนวณเลขคณิตภายในลูปของระดับได้ ในไพธอน 3 ให้ใช้การหารด้วยจำนวนทศนิยมเสมอ (ตัวดำเนินการ /) และจัดการกรณีต้นไม้ว่างตั้งแต่เริ่มต้น
from collections import deque
def average_of_levels(root):
if not root:
return []
result = []
q = deque([root])
while q:
size = len(q)
total = 0
for _ in range(size):
node = q.popleft()
total += node.val
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
result.append(total / size)
return result
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(average_of_levels(root)) # [3.0, 14.5, 11.0]ความลึกต่ำสุดด้วย BFS
ความลึกต่ำสุด คือระยะทางจากรากไปยังโหนด ใบ ที่อยู่ใกล้ที่สุด (โหนดที่ไม่มีโหนดลูก) BFS ค้นหาค่านี้ได้อย่างมีประสิทธิภาพสูงสุด เพราะโหนดใบแรกที่พบระหว่างการท่องตามระดับจะอยู่ที่ความลึกต่ำสุดอย่างแน่นอน ให้คืนค่าความลึกปัจจุบันทันทีที่พบโหนดใบ กรณีแย่ที่สุดใช้เวลา O(n) แต่สำหรับต้นไม้สมดุลมักจะสิ้นสุดเร็วกว่านั้นมาก
from collections import deque
def min_depth(root):
if not root:
return 0
q = deque([(root, 1)])
while q:
node, depth = q.popleft()
# A leaf has no children
if not node.left and not node.right:
return depth
if node.left:
q.append((node.left, depth + 1))
if node.right:
q.append((node.right, depth + 1))
return 0
root = TreeNode(2)
root.left = TreeNode(3)
root.left.left = TreeNode(4)
root.right = TreeNode(5) # leaf at depth 2
print(min_depth(root)) # 2การเชื่อมโยงโหนดพี่น้องตามระดับ
โจทย์ เติมตัวชี้ไปทางขวาถัดไป ให้คุณเชื่อมโยงแต่ละโหนดไปยังโหนดข้างขวาที่อยู่ในระดับเดียวกัน เมื่อใช้ BFS วิธีนี้ทำได้ตรงไปตรงมา โดยภายในลูปของแต่ละระดับ ให้กำหนด node.next = q[0] สำหรับทุกโหนดยกเว้นโหนดสุดท้าย นี่เป็นตัวอย่างคลาสสิกที่ BFS ทำให้เห็นวิธีแก้ได้อย่างชัดเจน ขณะที่ DFS ต้องติดตามตัวชี้ข้ามต้นไม้ย่อยอย่างระมัดระวัง
from collections import deque
class Node:
def __init__(self, val=0, left=None, right=None, next=None):
self.val = val
self.left = left
self.right = right
self.next = next
def connect(root):
if not root:
return root
q = deque([root])
while q:
size = len(q)
for i in range(size):
node = q.popleft()
if i < size - 1:
node.next = q[0]
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return root
print('BFS connect: O(n) time, O(w) space')ตรวจสอบอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิดโครงสร้างข้อมูล & อัลกอริทึม — การเตรียมตัวสัมภาษณ์เขียนโปรแกรมจากบทเรียนนี้
บทสรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้: การนิยามคลาส TreeNode และการสร้างต้นไม้จากอาร์เรย์ การใช้ BFS ตามระดับด้วยดีคิว โดยใช้เทคนิคขนาดระดับเพื่อจัดกลุ่มโหนด และ การประยุกต์ใช้ ซึ่งรวมถึงความลึกสูงสุด ความลึกต่ำสุด มุมมองด้านขวา การท่องแบบซิกแซ็ก และค่าเฉลี่ยของแต่ละระดับ บทถัดไปเราจะสำรวจลำดับการท่องแบบ DFS ด้วยการเรียกซ้ำ
คำถามที่พบบ่อย
บทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ”
สร้างต้นไม้ทวิภาคจากอาร์เรย์ สร้าง BFS ด้วย deque เพื่อพิมพ์ทีละระดับ และแก้โจทย์ความลึกสูงสุดด้วย BFS คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม
ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คลาส TreeNode และ BFS แบบเรียงตามระดับ
- DFS แบบลำดับกลาง ก่อน และหลัง
- เส้นผ่านศูนย์กลาง ความสูง และต้นไม้สมดุล
- ผลรวมเส้นทางและบรรพบุรุษร่วมที่ใกล้ที่สุด