- Binary tree traversal: preorder -> 中左右;inorder->左中右;postorder->左右中
// 144. Binary Tree Preorder Traversal
// Method 1: traverse
vector<int> ans;
vector<int> preorderTraversal(TreeNode* root) {
if (!root) return {};
ans.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
return ans;
}
// Method 2: non-recursive
vector<int> preorderTraversal(TreeNode* root) {
if (!root) return {};
vector<int> ans;
stack<TreeNode*> record;
record.push(root);
while (!record.empty()) {
const auto tp = record.top();
ans.push_back(tp->val);
record.pop();
if (tp->right != nullptr) record.push(tp->right);
if (tp->left != nullptr) record.push(tp->left);
}
return ans;
}
// 94. Binary Tree Inorder Traversal
// Method 1
vector<int> ans;
vector<int> inorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
inorderTraversal(root->left);
ans.push_back(root->val);
inorderTraversal(root->right);
return ans;
}
// Method 2
vector<int> inorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
stack<TreeNode*> record;
vector<int> ans;
while (root != nullptr || !record.empty()) {
while (root !=nullptr) {
record.push(root);
root = root->left;
}
root = record.top();
ans.push_back(root->val);
record.pop();
root = root->right;
}
return ans;
}
// 145. Binary Tree Postorder Traversal
// Method 1
vector<int> ans;
vector<int> postorderTraversal(TreeNode* root) {
if (!root) return {};
postorderTraversal(root->left);
postorderTraversal(root->right);
ans.push_back(root->val);
return ans;
}
// Method 2
vector<int> postorderTraversal(TreeNode* root) {
if (!root) return {};
stack<TreeNode*> record;
record.push(root);
vector<int> ans;
while (root != nullptr && !record.empty()) {
const auto tp = record.top();
ans.push_back(tp->val);
record.pop();
if (tp->left) record.push(tp->left);
if (tp->right) record.push(tp->right);
}
reverse(ans.begin(), ans.end());
return ans;
}
// 589. N-ary Tree Preorder Traversal
void PreorderTraversal(Node* root, vector<int>& nums) {
if (root == nullptr) return;
nums.push_back(root->val);
for (const auto ptr : root->children) {
PreorderTraversal(ptr, nums);
}
}
vector<int> preorder(Node* root) {
vector<int> pre_nums;
PreorderTraversal(root, pre_nums);
return pre_nums;
}
// 590. N-ary Tree Postorder Traversal
void PostOrderTraversal(Node* root, vector<int>& nums) {
if (root == nullptr) return;
for (const auto ptr : root->children)
PostOrderTraversal(ptr, nums);
nums.push_back(root->val);
}
vector<int> postorder(Node* root) {
vector<int> nums;
PostOrderTraversal(root, nums);
return nums;
}
// 429. N-ary Tree Level Order Traversal
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> ans;
queue<Node*> cur_level;
if (root != nullptr) cur_level.push(root);
while (!cur_level.empty()) {
vector<int> cur_nums;
int size = cur_level.size();
for (int idx = 0; idx < size; ++idx) {
const auto ptr = cur_level.front();
cur_level.pop();
cur_nums.push_back(ptr->val);
for (const auto ptr2 : ptr->children)
if (ptr2 != nullptr) cur_level.push(ptr2);
}
ans.push_back(cur_nums);
}
return ans;
}
// 776. Split BST
vector<TreeNode*> splitBST(TreeNode* root, int target) {
vector<TreeNode*> ans(2, nullptr);
if (!root) return ans;
if (root->val > target) {
ans[1] = root;
const auto res = splitBST(root->left, target);
root->left = res[1];
ans[0] = res[0];
} else {
ans[0] = root;
const auto res = splitBST(root->right, target);
root->right = res[0];
ans[1] = res[1];
}
return ans;
}
- Level Order Traversal
// 102. Binary Tree Level Order Traversal
vector<vector<int>> levelOrder(TreeNode* root) {
if (root == nullptr) return {};
vector<vector<int>> ans;
queue<TreeNode*> record;
record.push(root);
while (!record.empty()) {
int len = record.size();
vector<int> level;
for (int idx = 0; idx < len; ++idx) {
const auto tp = record.front();
level.push_back(tp->val);
record.pop();
if (tp->left != nullptr) record.push(tp->left);
if (tp->right != nullptr) record.push(tp->right);
}
ans.push_back(level);
}
return ans;
}
// Method 2
void LevelOrderBottom(TreeNode* root, int level) {
if (!root) return;
if (ans.size() <= level) ans.push_back({});
ans[level].push_back(root->val);
LevelOrderBottom(root->left, level + 1);
LevelOrderBottom(root->right, level + 1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
LevelOrderBottom(root, 0);
return ans;
}
// 107. Binary Tree Level Order Traversal II
// Method 1 BFS
vector<vector<int>> levelOrderBottom(TreeNode* root) {
if (root == nullptr) return {};
vector<vector<int>> ans;
queue<TreeNode*> record;
record.push(root);
while (!record.empty()) {
int len = record.size();
vector<int> level;
for (int idx = 0; idx < len; ++idx) {
const auto tp = record.front();
level.push_back(tp->val);
record.pop();
if (tp->left != nullptr) record.push(tp->left);
if (tp->right != nullptr) record.push(tp->right);
}
ans.push_back(level);
}
reverse(ans.begin(), ans.end());
return ans;
}
// Method 2 DFS
vector<vector<int>> ans;
void LevelOrderBottom(TreeNode* root, int level) {
if (!root) return;
if (ans.size() <= level) ans.push_back({});
ans[level].push_back(root->val);
LevelOrderBottom(root->left, level + 1);
LevelOrderBottom(root->right, level + 1);
}
vector<vector<int>> levelOrderBottom(TreeNode* root) {
LevelOrderBottom(root, 0);
reverse(ans.begin(), ans.end());
return ans;
}
// 103. Binary Tree Zigzag Level Order Traversal
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
if (!root) return {};
vector<vector<int>> ans;
queue<TreeNode*> cur_level;
cur_level.push(root);
bool is_odd = true;
while (!cur_level.empty()) {
int size = cur_level.size();
int idx = 0;
vector<int> cur_value;
while (idx < size) {
const auto tp = cur_level.front();
cur_value.push_back(tp->val);
cur_level.pop();
if (tp->left) cur_level.push(tp->left);
if (tp->right) cur_level.push(tp->right);
++idx;
}
if (!is_odd) {
reverse(cur_value.begin(), cur_value.end());
}
ans.push_back(cur_value);
is_odd ^= 1;
}
return ans;
}
// 255. Verify Preorder Sequence in Binary Search Tree
bool VerifyPreorder(vector<int>& nums, int stt_idx,
int fin_idx, int val, bool is_right) {
if (fin_idx <= stt_idx) return true;
if (is_right) {
for (int idx = stt_idx; idx <= fin_idx; ++idx) {
if (nums[idx] < val) return false;
}
}
int new_val = nums[stt_idx];
int cut_idx = stt_idx;
for (int idx = stt_idx; idx <= fin_idx; ++idx) {
if (nums[idx] > new_val) {
cut_idx = idx - 1;
break;
} else cut_idx = idx;
}
return VerifyPreorder(nums, stt_idx + 1, cut_idx,
new_val, false) &&
VerifyPreorder(nums, cut_idx + 1, fin_idx,
new_val, true);
}
bool verifyPreorder(vector<int>& preorder) {
return VerifyPreorder(preorder, 0, preorder.size() - 1,
INT_MIN, true);
}
// 366. Find Leaves of Binary Tree
int FindLeaves(TreeNode* root, vector<vector<int>>& record) {
if (!root) return -1;
if (!root->left && !root->right) {
if (!record.size()) record.emplace_back(vector<int>());
record[0].emplace_back(root->val);
return 0;
}
const int index_left = FindLeaves(root->left, record);
const int index_right = FindLeaves(root->right, record);
const int index_root = max(index_left, index_right) + 1;
if (record.size() < index_root + 1)
record.emplace_back(vector<int>());
record[index_root].emplace_back(root->val);
return index_root;
}
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> ans;
FindLeaves(root, ans);
return ans;
}
// 428. Serialize and Deserialize N-ary Tree
class Codec {
public:
// Encodes a tree to a single string.
string serialize(Node* root) {
if (!root) return "";
string ans = "(" + to_string(root->val);
for (const auto ptr : root->children) {
ans += serialize(ptr);
}
ans += ")";
return ans;
}
// Decodes your encoded data to tree.
std::string::size_type sz;
Node* deserialize(string data) {
if (data.empty()) return nullptr;
string data2 = data.substr(1, data.size()-2);
if (data2.empty()) return nullptr;
string cur;
int count = 0;
int i = 0;
while (data2[i] >= '0' && data2[i] <= '9') {
cur += data2[i];
++i;
}
Node* head = new Node(stoi(cur, &sz));
cur.clear();
while (i < data2.size()) {
if (data2[i] == '(') {
++count;
cur += data2[i];
} else if (data2[i] == ')') {
--count;
cur += data2[i];
if (!count) {
head->children.emplace_back(deserialize(cur));
cur.clear();
}
} else cur += data2[i];
++i;
}
if (!cur.empty()) head->children.emplace_back(deserialize(cur));
return head;
}
};
- Construct binary tree from different orders
// 105. Construct Binary Tree from Preorder and Inorder Traversal
TreeNode* BuildTree(vector<int>& preorder, int pre_stt_idx, int pre_fin_idx,
vector<int>& inorder, int in_stt_idx, int in_fin_idx) {
if (pre_stt_idx > pre_fin_idx) return nullptr;
if (pre_stt_idx == pre_fin_idx) return new TreeNode(preorder[pre_stt_idx]);
int root_val = preorder[pre_stt_idx];
int left_idx = in_stt_idx;
while (inorder[left_idx] != root_val) ++left_idx;
int num_left = left_idx - in_stt_idx;
TreeNode* left_node = BuildTree(preorder, pre_stt_idx + 1,
pre_stt_idx + num_left,
inorder, in_stt_idx, left_idx - 1);
TreeNode* right_node = BuildTree(preorder, pre_stt_idx + num_left + 1,
pre_fin_idx, inorder,
left_idx + 1, in_fin_idx);
return new TreeNode(root_val, left_node, right_node);
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return BuildTree(preorder, 0, preorder.size() - 1,
inorder, 0, inorder.size() - 1);
}
// 889. Construct Binary Tree from Preorder and Postorder Traversal
TreeNode* BuildTree(vector<int>& inorder, int in_stt_idx, int in_fin_idx,
vector<int>& postorder, int post_stt_idx,
int post_fin_idx) {
if (in_stt_idx > in_fin_idx) return nullptr;
if (in_stt_idx == in_fin_idx) return new TreeNode(inorder[in_stt_idx]);
unordered_map<int, int> record;
int root_val = inorder[in_stt_idx];
int num = 0;
while (num < in_fin_idx - in_stt_idx) {
int in_val = inorder[in_stt_idx + 1 + num];
int post_val = postorder[post_stt_idx + num];
++record[in_val];
--record[post_val];
++num;
if (!record[in_val]) record.erase(in_val);
if (!record[post_val]) record.erase(post_val);
if (record.empty()) break;
}
TreeNode* left_node = BuildTree(inorder, in_stt_idx + 1,
in_stt_idx + num, postorder,
post_stt_idx, post_stt_idx + num - 1);
TreeNode* right_node = BuildTree(inorder, in_stt_idx + num + 1,
in_fin_idx, postorder,
post_stt_idx + num, post_fin_idx - 1);
return new TreeNode(root_val, left_node, right_node);
}
TreeNode* constructFromPrePost(vector<int>& inorder, vector<int>& postorder) {
return BuildTree(inorder, 0, inorder.size() - 1,
postorder, 0, postorder.size() - 1);
}
// 106. Construct Binary Tree from Inorder and Postorder Traversal
TreeNode* BuildTree(vector<int>& inorder, int in_stt_idx, int in_fin_idx,
vector<int>& postorder, int post_stt_idx,
int post_fin_idx) {
if (in_stt_idx > in_fin_idx) return nullptr;
if (in_stt_idx == in_fin_idx) return new TreeNode(inorder[in_stt_idx]);
int root_val = postorder[post_fin_idx];
int left_idx = in_stt_idx;
while (inorder[left_idx] != root_val) ++left_idx;
int left_num = left_idx - in_stt_idx;
TreeNode* left_node = BuildTree(inorder, in_stt_idx,
in_stt_idx + left_num - 1, postorder,
post_stt_idx, post_stt_idx + left_num - 1);
TreeNode* right_node = BuildTree(inorder, in_stt_idx + left_num + 1,
in_fin_idx, postorder,
post_stt_idx + left_num, post_fin_idx - 1);
return new TreeNode(root_val, left_node, right_node);
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return BuildTree(inorder, 0, inorder.size() - 1,
postorder, 0, postorder.size() - 1);
}
// 1008. Construct Binary Search Tree from Preorder Traversal
TreeNode* BstFromPreorder(vector<int>& preorder,
int stt_idx, int fin_idx) {
if (stt_idx > fin_idx) return nullptr;
if (stt_idx == fin_idx) return new TreeNode(preorder[stt_idx]);
int root_val = preorder[stt_idx];
int left_idx = stt_idx + 1;
while (left_idx < preorder.size() &&
preorder[left_idx] < root_val) ++left_idx;
TreeNode* left = BstFromPreorder(preorder, stt_idx + 1, left_idx - 1);
TreeNode* right = BstFromPreorder(preorder, left_idx, fin_idx);
return new TreeNode(root_val, left, right);
}
TreeNode* bstFromPreorder(vector<int>& preorder) {
return BstFromPreorder(preorder, 0, preorder.size() - 1);
}
// 971. Flip Binary Tree To Match Preorder Traversal
// Find right border with fin_idx; change child if needed.
vector<int> flip_vec;
bool FlipMatchVoyage(TreeNode* root, vector<int>& voyage,
int stt_idx, int fin_idx) {
if (root == nullptr && stt_idx > fin_idx) return true;
if (voyage[stt_idx] != root->val) return false;
if (stt_idx == fin_idx && (!root->left && !root->right))
return true;
int left_root_val = root->left == nullptr?-1:root->left->val;
int right_root_val = root->right == nullptr?-1:root->right->val;
if (left_root_val != voyage[stt_idx + 1] &&
right_root_val != voyage[stt_idx + 1]) return false;
if (root->left != nullptr && left_root_val != voyage[stt_idx+1]) {
swap(root->left, root->right);
flip_vec.push_back(root->val);
}
right_root_val = root->right == nullptr?-1:root->right->val;
int left_idx = stt_idx + 1;
while (left_idx <= fin_idx && voyage[left_idx] != right_root_val)
++left_idx;
bool left_res = FlipMatchVoyage(root->left, voyage,
stt_idx + 1, left_idx - 1);
if (!left_res) return false;
bool right_res = FlipMatchVoyage(root->right, voyage,
left_idx, fin_idx);
return right_res;
}
vector<int> flipMatchVoyage(TreeNode* root, vector<int>& voyage) {
bool flip_res = FlipMatchVoyage(root, voyage, 0, voyage.size() - 1);
if (!flip_res) return {-1};
return flip_vec;
}
// Left & right merge
// 96. Unique Binary Search Trees
int record[20][20];
int GetUniqueSearch(const int stt, const int fin) {
if (stt > fin) return 1;
if (record[stt][fin] > 0)
return record[stt][fin];
int ttl_num = 0;
for (int index = stt; index <= fin; ++index) {
ttl_num += GetUniqueSearch(stt, index-1) * GetUniqueSearch(index+1, fin);
}
record[stt][fin] = ttl_num;
return record[stt][fin];
}
int numTrees(int n) {
memset(record, 0, sizeof(record));
return GetUniqueSearch(1, n);
}
// 95. Unique Binary Search Trees II
vector<TreeNode*> GetUniqueTree(const int stt, const int fin) {
if (stt > fin) return {nullptr};
if (stt == fin) {
return {new TreeNode(stt)};
}
vector<TreeNode*> ans;
for (int index = stt; index <= fin; ++index) {
vector<TreeNode*> left = GetUniqueTree(stt, index-1);
vector<TreeNode*> right = GetUniqueTree(index+1, fin);
for (const auto l : left) {
for (const auto r : right) {
TreeNode* root = new TreeNode(index);
root->left = l;
root->right = r;
ans.emplace_back(root);
}
}
}
return ans;
}
vector<TreeNode*> generateTrees(int n) {
if (n <= 0) {
return {};
}
return GetUniqueTree(1, n);
}
// 99. Recover Binary Search Tree
// Method 1: iterative with inorder
void recoverTree(TreeNode* root) {
stack<TreeNode*> record;
TreeNode* last_node = nullptr;
TreeNode* x = nullptr;
TreeNode* y = nullptr;
while (root || !record.empty()) {
while (root) {
record.emplace(root);
root = root->left;
}
TreeNode* cur_node = record.top();
record.pop();
if (cur_node->right)
root = cur_node->right;
if (last_node && cur_node->val < last_node->val) {
y = cur_node;
if (!x) x = last_node;
else break;
}
last_node = cur_node;
}
const int val = y->val;
y->val = x->val;
x->val = val;
}
// Method 2: recursion
TreeNode* x = nullptr;
TreeNode* y = nullptr;
TreeNode* last = nullptr;
void Swap(TreeNode* x, TreeNode* y) {
if (!x || !y) return;
const int val = x->val;
x->val = y->val;
y->val = val;
}
void recoverTree(TreeNode* root) {
RecoverTree(root);
Swap(x, y);
}
void RecoverTree(TreeNode* root) {
if (!root) return;
RecoverTree(root->left);
if (last && last->val > root->val) {
y = root;
if (!x) {
x = last;
} else return;
}
last = root;
RecoverTree(root->right);
}
- BST Succesor
// 285. Inorder Successor in BST
// Method 1
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (root == nullptr || p == nullptr) return nullptr;
TreeNode* ans = nullptr;
const int p_val = p->val;
while (root != nullptr) {
if (root->val > p_val) {
ans = root;
root = root->left;
} else {
root = root->right;
}
}
return ans;
}
// Method 2
void inorderSuccessorNode(TreeNode* const root, TreeNode* const p, TreeNode* &ans) {
if(!root) return;
if (root->val > p->val) {
if (ans == nullptr || root->val < ans->val) {
ans = root;
}
inorderSuccessorNode(root->left, p, ans);
} else {
inorderSuccessorNode(root->right, p, ans);
}
}
// 510. Inorder Successor in BST II
Node* inorderSuccessor(Node* node) {
if (node == nullptr) return nullptr;
Node* cur_node = node;
Node* cur_right = node->right;
if (cur_right != nullptr) {
while (cur_right->left != nullptr) {
cur_right = cur_right->left;
}
}
if (cur_right != nullptr) return cur_right;
while (cur_node->parent != nullptr) {
if (cur_node->parent->left == cur_node) {
return cur_node->parent;
}
cur_node = cur_node->parent;
}
return nullptr;
}
// 987. Vertical Order Traversal of a Binary Tree
//positioning based and replicate position
void VerticalTraversal(TreeNode* root, int row, int col,
map<int, map<int, multiset<int>>>& record) {
if (!root) return;
record[col][row].insert(root->val);
VerticalTraversal(root->left, row + 1, col - 1, record);
VerticalTraversal(root->right, row + 1, col + 1, record);
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
map<int, map<int, multiset<int>>> record;
VerticalTraversal(root, 0, 0, record);
vector<vector<int>> ans;
for (const auto line : record) {
const auto line_data = line.second;
vector<int> line_vec;
for (const auto ele : line_data) {
const auto nums = ele.second;
for (const auto num : nums) {
line_vec.push_back(num);
}
}
ans.push_back(line_vec);
}
return ans;
}
// 116. Populating Next Right Pointers in Each Node
Node* connect(Node* root) {
if (!root) return nullptr;
if (root->left) {
root->left->next = root->right;
}
if (root->right && root->next) {
root->right->next = root->next->left;
}
connect(root->right);
connect(root->left);
return root;
}
// 117. Populating Next Right Pointers in Each Node II
Node* connect(Node* root) {
if (!root) return nullptr;
if (root->left && root->right) {
root->left->next = root->right;
}
if ((root->left && !root->right) || (root->right && !root->left) || (root->left && root->right)) {
auto node = root->next;
Node* cur_node = !root->right ? root->left : root->right;
while (node) {
if (node->left || node->right) {
cur_node->next = node->left ? node->left : node->right;
break;
}
node = node->next;
}
}
connect(root->right);
connect(root->left);
return root;
}
// 272. Closest Binary Search Tree Value II
// O(n) solution
deque<int> data_;
vector<int> closestKValues(TreeNode* root, double target, int k) {
Inorder(root);
while (data_.size() > k) {
const double diff_prev = abs(data_.front() - target);
const double diff_suc = abs(data_.back() - target);
if (diff_prev > diff_suc) {
data_.pop_front();
} else {
data_.pop_back();
}
}
return vector<int>(begin(data_), end(data_));
}
void Inorder(const TreeNode* root) {
if (!root) return;
Inorder(root->left);
data_.emplace_back(root->val);
Inorder(root->right);
}
// Another solution is the iterative solution with successor and pre.
// 450. Delete Node in a BST
TreeNode* deleteNode(TreeNode* root, int key) {
if (!root) return nullptr;
TreeNode* parent = nullptr;
TreeNode* cur = root;
while (cur != nullptr) {
if (cur->val > key) {
parent = cur;
cur = cur->left;
} else if (cur->val < key) {
parent = cur;
cur = cur->right;
} else {
break;
}
}
if (!cur) return root;
TreeNode* mark = cur;
if (cur->left) {
parent = cur;
cur = cur->left;
while (cur->right) {
parent = cur;
cur = cur->right;
}
mark->val = cur->val;
if (parent->left == cur)
parent->left = cur->left;
else parent->right = cur->left;
} else if (cur->right) {
parent = cur;
cur = cur->right;
while (cur->left) {
parent = cur;
cur = cur->left;
}
mark->val = cur->val;
if (parent->right == cur)
parent->right = cur->right;
else
parent->left = cur->right;
} else {
if (!parent) return nullptr;
if (parent->left == cur) parent->left = nullptr;
if (parent->right == cur) parent->right = nullptr;
}
return root;
}
