ปัญหา: Boundary of Binary Tree
กำหนด Binary Tree หา ขอบ (boundary) ในทิศทาง วนทวนเข็มนาฬิกา เริ่มจากราก
ประกอบด้วย 3 ส่วน (ไม่ซ้ำโหนด):
- Left Boundary: ราก → โหนดซ้ายสุด (ไม่รวมใบ)
- Leaves: ใบทั้งหมด (ซ้ายไปขวา)
- Right Boundary: โหนดขวาสุด → ราก (ไม่รวมใบ, เรียกทวนลำดับ)
ตัวอย่าง
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \
8 9 10
Boundary: [1, 2, 4, 8, 9, 10, 6, 7, 3]
แนวทางแก้ปัญหา: 3 DFS แยกส่วน
Left Boundary
จาก root->left ลงไป: เพิ่มโหนด → ถ้ามีซ้าย ไปซ้าย ไม่งั้นไปขวา → หยุดที่ใบ
Right Boundary
จาก root->right ลงไป: ถ้ามีขวา ไปขวา ไม่งั้นไปซ้าย → หยุดที่ใบ → เพิ่มโหนดตอน backtrack (เพื่อให้เรียงจากใต้ขึ้นมา)
Leaves
Inorder traversal: เพิ่มโหนดที่ไม่มีลูก
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
vector<int> boundary;
void leftBoundary(TreeNode* node) {
if (!node || (!node->left && !node->right)) return;
boundary.push_back(node->val);
if (node->left) leftBoundary(node->left);
else leftBoundary(node->right);
}
void rightBoundary(TreeNode* node) {
if (!node || (!node->left && !node->right)) return;
if (node->right) rightBoundary(node->right);
else rightBoundary(node->left);
boundary.push_back(node->val); // post-order: add after children
}
void leaves(TreeNode* node) {
if (!node) return;
if (!node->left && !node->right) {
boundary.push_back(node->val);
return;
}
leaves(node->left);
leaves(node->right);
}
public:
vector<int> boundaryOfBinaryTree(TreeNode* root) {
boundary.clear();
if (!root) return boundary;
boundary.push_back(root->val);
leftBoundary(root->left);
leaves(root->left);
leaves(root->right);
rightBoundary(root->right);
return boundary;
}
};
int main() {
Solution ob;
// Build tree from example
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->left = new TreeNode(6);
root->right->right = new TreeNode(7);
root->left->left->left = new TreeNode(8);
root->left->left->right = new TreeNode(9);
root->right->left->left = new TreeNode(10);
auto ans = ob.boundaryOfBinaryTree(root);
for (int x : ans) cout << x << ' '; // 1 2 4 8 9 10 6 7 3
return 0;
}
ความซับซ้อน
- เวลา: O(N) – เยี่ยมทุกโหนดคงที่ครั้ง
- พื้นที่: O(H) – recursion stack, H = ความสูง
ข้อสังเกต
- LeetCode 545
- สำคัญ: Right boundary ต้องเพิ่มค่า หลัง recursion (post-order) เพื่อให้เรียงจากใต้ขึ้น
- Left boundary และ Right boundary ไม่รวมใบ – ใบจัดการใน leaves()
- กรณี root ไม่มี left/right subtree → root เองเป็น boundary นั้น