Given the root
of a binary tree, return its maximum depth.
A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: 3
Example 2:
Input: root = [1,null,2]
Output: 2
DFS: traversing depth first
์ฌ๊ท์ ์ผ๋ก ์๊ฐํ๋ฉด ๊ฐ๋จํ๋ค
์ผ๋จ ํ์ฌ root๊ฐ null ํฌ์ธํฐ๋ผ๋ฉด length๋ 0
์๋๋ผ๋ฉด leftchild ์ rightchild์ค์ ๋ ๊น์ depth๋ฅผ ๊ฐ์ง์ ๋ฅผ ์ฐพ์์ +1
์ ํด์ค๋ค
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
};
BFS: traversing level by level
number of level = number of depth
๊ทธ๋์,, queue๋ฅผ ์ด์ฉํด์ ๊ทธ๋ฅ level์๋ฅผ ์ธ๋ฉด ๋๋ค~!
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) {
return 0;
}
queue<TreeNode*> q;
q.push(root);
int result = 0;
while (!q.empty()) {
int count = q.size();
for (int i = 0; i < count; i++) {
TreeNode* node = q.front();
q.pop();
if (node->left != NULL) {
q.push(node->left);
}
if (node->right != NULL) {
q.push(node->right);
}
}
result++;
}
return result;
}
};
์์ ๊ฐ์ ๋ฌธ์ ์ด์ง๋ง ์ด๋ฒ์ minimum depth ๋ฅผ ์ฐพ์๋ณด์
์์ ์ฝ๋๋ฅผ ์กฐ๊ธ๋ง ๋ฐ๊พธ๋ฉด ๋๊ฒ ๋ค
์ฃผ์ํด์ผํ ๋ถ๋ถ์ leafnode์ depth๋ฅผ ์ธ์ง ์๋๋ก ํ๋ ๊ฒ ์ด๋ค
leafnode์ minDepth
๋ฅผ ๋๋ฆฐ๋ค๋ฉด 0
์ด ๋์ค๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ์ min ๊ฐ์ด ์ํฅ์ ๋ฐ๋๋ค
์์์ด ํ๋๋ง ์๋ค๋ฉด:
null์ด ์๋ ์์์๊ฒ๋ง recursion์ ๋๋ ค์ผํ๋ค
(completely unbalanced tree๋ฅผ ์๊ฐํด๋ณด์)
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) return 0; //์ง์ง root๋ง ์ฌ๊ธฐ condition์ ํด๋น
if (!root->left && !root->right) return 1; //leafnode
// ์์์ด ์กด์ฌํ๋ค๋ ๊ฒฝ์ฐ์๋ง ๊ทธ์์์ ๋ํ minDepth๋ฅผ ์คํํ๋ค
// ์์์ด ์กด์ฌํ์ง ์๋ค๋ฉด depthend์ด๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ์ min ๊ณ์ฐ์ ์ํฅ์ ์ฃผ์ง ์๋๋ก INT_MAX๋ก ์ง์ ํ๋ค
int left = root->left ? minDepth(root->left) : INT_MAX;
int right = root->right ? minDepth(root->right) : INT_MAX;
return min(left, right) + 1;
}
};
ํต์ฌ์: leafnode๋ฅผ ๋ง๋๋ ์๊ฐ์ด min depth์ด๋ค!
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) {
return 0;
}
queue<TreeNode*> q;
q.push(root);
int result = 1;
while (!q.empty()) {
int count = q.size();
for (int i = 0; i < count; i++) {
TreeNode* node = q.front();
q.pop();
// if the node is a leafnode, min depth is here
if (!node->left && !node->right) return result;
// else push children into the queue and calculate the next level
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result++;
}
return result;
}
};
You are given two binary trees root1
and root2
.
Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of the new tree.
Return the merged tree.
Note: The merging process must start from the root nodes of both trees.
Example 1:
Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
Output: [3,4,5,5,4,null,7]
Example 2:
Input: root1 = [1], root2 = [1,2]
Output: [2,2]
์ค ์ฝ๋ค!
ํ๋ฒ์ ํ์๋น
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode *merged;
if (root1 && root2) {
// overlapping nodes
int val = root1->val + root2->val;
merged = new TreeNode(val);
merged->left = mergeTrees(root1->left, root2->left);
merged->right= mergeTrees(root1->right, root2->right);
} else {
// if not overlapping nodes
if (root1) {
merged = root1;
} else {
merged = root2;
}
}
return merged;
}
};
Given an integer array nums
where the elements are sorted in ascending order, convert it to a height-balanced binary search tree.
Example 1:
Input: nums = [-10,-3,0,5,9]
Output: [0,-3,9,-10,null,5]
Explanation: [0,-10,5,null,-3,null,9] is also accepted:
Example 2:
Input: nums = [1,3]
Output: [3,1]
Explanation: [1,null,3] and [3,1] are both height-balanced BSTs.
๊ฐ์ด๋ฐ๋ฅผ ๋๋ ์ ๊ทธ ๊ฐ์ด๋ฐ๋ฅผ ๊ธฐ์ค์ผ๋ก root๋ผ๊ณ ํ๊ณ ์์์ ๊ฐ๊ฐ์ left, right children์๊ฒ ์ค๋ค!
์๋ ๋๊ฒ ๊ฐ๋จํ ๋ฌธ์ ๋ฐ vector slicing ํ๋๊ฑฐ ๋ญ ํ๋ ๊ฒ ๋ง๋ค ์ค๋ฅ๋จ๋ ๊ฐ๋นข์น๋ค
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
if (nums.size() == 0) return NULL;
int mid = nums.size() / 2 ;
TreeNode *node = new TreeNode(nums[mid]);
vector<int> left(nums.begin(), nums.begin() + mid);
vector<int> right(nums.begin() + mid + 1, nums.end());
node->left = sortedArrayToBST(left);
node->right = sortedArrayToBST(right);
return node;
}
};
ํด ๋๋์ด ๋๋ค!!
Given the root
of a binary tree and an integer targetSum
, return true
if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum
.
Example 1:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
Output: true
Explanation: The root-to-leaf path with the target sum is shown.
Example 2:
Input: root = [1,2,3], targetSum = 5
Output: false
Explanation: There two root-to-leaf paths in the tree:
(1 --> 2): The sum is 3.
(1 --> 3): The sum is 4.
There is no root-to-leaf path with sum = 5.
Example 3:
Input: root = [], targetSum = 0
Output: false
Explanation: Since the tree is empty, there are no root-to-leaf paths.
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
int val = root->val;
if (targetSum - val == 0 && !root->left && !root->right) return true;
return hasPathSum(root->left, targetSum - val) || hasPathSum(root->right, targetSum - val);
}
};
Given the root
of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]
Example 2:
Input: root = [1]
Output: [[1]]
Example 3:
Input: root = []
Output: []
outputํํ๋ฅผ ๋ณด๋ฉด ~ ์ด๊ฑฐ๋ ๋ฑ๋ด๋ recursion ์๋๊ณ iteration BFS๋ค!
Queue๋ฅผ ์ฐ์!!
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
if (root == NULL) return result;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
vector<int> cur_level;
int n = q.size();
// for each level
for (int i = 0; i < n; i++) {
TreeNode *node = q.front();
q.pop();
cur_level.push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result.push_back(cur_level);
}
return result;
}
};
Given the root
of a binary tree, return the zigzag level order traversal of its nodes' values. (i.e., from left to right, then right to left for the next level and alternate between).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[20,9],[15,7]]
Example 2:
Input: root = [1]
Output: [[1]]
Example 3:
Input: root = []
Output: []
๋ฐ๋ก ์ด์ ๋ฌธ์ ๋ฅผ ๊ฐ๋ค ์จ์ ์ค์ ๋ต์ ๋ง๋ค์ด ์ค๋ right โ left ํด์ค์ผ ํ๋ level์์๋ ์ซ์๋ฅผ ๋ต vector์์ ์์๋ค๊ฐ ์ฝ์ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ํ๋ค
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> result;
if (root == NULL) return result;
queue<TreeNode*> q;
q.push(root);
int level = 1;
while (!q.empty()) {
vector<int> cur_level;
int n = q.size();
// for each level
for (int i = 0; i < n; i++) {
TreeNode *node = q.front();
q.pop();
if (level % 2 == 0) {
// right->left ์ผ๋๋ vector์ ์์๋ค๊ฐ ์ฝ์
ํด์ค๋ค
cur_level.insert(cur_level.begin(), node->val);
} else {
// left->right ์ผ๋๋ ์์๋๋ก ๋ค์ด๊ฐ๋๋ก ์๋์ฒ๋ผ push ํด์ค๋ค
cur_level.push_back(node->val);
}
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result.push_back(cur_level);
level++;
}
return result;
}
};
Given the root
of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
Input: root = [2,1,3]
Output: true
Example 2:
Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
ํด๋น subtree๊ฐ ๊ฐ์ง ์ ์๋ min๊ฐ๊ณผ max๊ฐ์ parameter์ ์ ์งํด์ ๋น๊ตํ ์ ์๊ฒ ํ๋ค
left child์ subtree์ ๊ฐ์ ํ์ฌ root๊ฐ ๋ณด๋ค ์ปค์๋ ์๋๋ค
right child์ subtree์ ๊ฐ์ ํ์ฌ root๊ฐ๋ณด๋ค ์์์๋ ์๋๋ค
class Solution {
public:
bool isValid(TreeNode* root, TreeNode* min, TreeNode* max) {
if(root == NULL) return true;
if(min && root->val <= min->val) return false;
if(max && root->val >= max->val) return false;
return isValid(root->left, min, root) && isValid(root->right, root, max);
}
bool isValidBST(TreeNode* root) {
return isValid(root, NULL, NULL);
}
};
Given two integer arrays preorder
and inorder
, construct and return the binary tree.
Example 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
Example 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
preorder,, inorder,, ์ด๊ฑฐ ๋ญ๊ฐ cs341์ธ๊ฐ์์ ๋ค ํ๋๊ฑฐ ๊ฐ์๋ฐ ์ง์ง ๋ ์ ๊ธฐ์ต 1๋ ์๋๋ค ,, ๋ฏธ์ณค
์ผ๋จ ์ด๊ฑฐ๋ผ๋ ๋ณด๋ฉด์ ๋ณต๊ธฐ๋ฅผ ํด๋ณด์,,,
์์ ์์์์๋ [1 2 3 4 5]๊ฐ ๋ ๊ฒ์ด๋ค
โผ๏ธ ์ด ๊ฐ๋
์ด ์ฝ๋์ index
์ ์ ์ฉ๋๋ค
root element๋ฅผ ์ฐพ์ผ๋ฉด ๊ทธ ๊ธฐ์ค์ผ๋ก
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int index = 0;
return build(preorder, inorder, index, 0, inorder.size() - 1);
}
private:
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int& index, int i, int j) {
// **
// * ์ผ๋จ index๋ฅผ ์ฃผ์ ๊ฐ์ผ๋ก ๋ฐ์ ๋ง์น global variable ์ธ๊ฑฐ์ฒ๋ผ ์ฌ์ฉํ์
// * *
// i์ j๋ inorder array์ index๊ฐ์ด๋ค
// ํ์ฌ node๊ฐ root๊ฐ ๋๋ ๊ธฐ์ค์ผ๋ก ๋ดค์ ๋ inorder array[i:j+1]๊ฐ ํด๋น๋๋ค
if (i > j) { // OOB
return NULL;
}
TreeNode* root = new TreeNode(preorder[index]);
int split = 0;
for (int i = 0; i < inorder.size(); i++) {
if (preorder[index] == inorder[i]) {
split = i;
break;
}
}
// **
// * preorder์ ํน์ง์ ์๊ฐํด๋ณด์
// * ์ผ์ชฝ์ ๋ค ์ดค๋ฅด๋ฅต ๋จผ์ ํ๊ณ ๊ทธ๋ด์ ์ค๋ฅธ์ชฝ์ ๋ค์ด ์์๋๋ค
// * ๋ฐ๋ผ์ ์ด index๋ฅผ ์์ฑ๋ function stack๋ง๋ค ํ์นธ์ฉ ์ฌ๋ ค์ฃผ๊ณ
// * index๋ ์ฃผ์๊ฐ์ ๋ฐ์์์ ์ด์ ๊ฐ์ด ์ ์ง๊ฐ ๋๋ฏ๋ก
// * ์ด๋ฐ๋ฐฉ์์ด ํตํ๋ ๊ฒ์ด๋ค
// **
index++;
// left build๊ฐ ๋ชจ๋ ๋๋์์ผ right build๊ฐ ์์๋๋ค
// index๋ฅผ ์ด๋ ๊ฒ ๊ฐํธํ๊ฒ ์ค ์ ์๋๊ฒ์ preorder์ ํน์ง ๋๋ถ
root->left = build(preorder, inorder, index, i, split - 1);
root->right = build(preorder, inorder, index, split + 1, j);
return root;
}
};
A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.
The path sum of a path is the sum of the node's values in the path.
Given the root
of a binary tree, return the maximum path sum of any non-empty path.
Example 1:
Input: root = [1,2,3]
Output: 6
Explanation: The optimal path is 2 -> 1 -> 3 with a path sum of 2 + 1 + 3 = 6.
Example 2:
Input: root = [-10,9,20,null,null,15,7]
Output: 42
Explanation: The optimal path is 15 -> 20 -> 7 with a path sum of 15 + 20 + 7 = 42.
์ด๊ฑด ์ฆ๋งฌ๋ฃจ ์ด๋ ต๋น ,, ํ์ง๋ง ๋ญ๊ฐ ์ธํฐ๋ทฐ์ ๋์ฌ๊ฒ ๊ฐ์ ์ง๋ฌธ์ด์ผ,,
class Solution {
public:
int maxPathSum(TreeNode* root) {
int maxPath = INT_MIN;
// maxPath is not updated when the path from root to leaf w/o split
// has the maxPath
// and the return value for this line will return such path
int m = dfs(root, maxPath);
return max(m, maxPath);
}
private:
int dfs(TreeNode *root, int &maxPath) {
if (root == NULL) return 0;
// this will compute the subtrees
// will not consider split in the subtree
// left and right each represent the maxPath from bottom to root->left/root->right without any splits
int left = max(dfs(root->left, maxPath), 0);
int right = max(dfs(root->right, maxPath), 0);
// we will eventually consider the split case in here
int cur_path = root->val + left + right;
maxPath = max(cur_path, maxPath);
// return "the maxPath from bottom to root without any splits"
return root->val + max(left, right);
}
};
class TrieNode { // alphabet nodes
public:
TrieNode* children[26];
bool isWord; // to mark that this is a word
TrieNode() {
for (int i = 0; i < 26; i++) {
children[i] = NULL;
}
isWord = false;
}
};
class Trie { // this is the rootnode (wrapper)
private:
TrieNode *root;
public:
Trie() {
root = new TrieNode();
}
void insert(string word) {
// start from the root
TrieNode *curr = root;
int n = word.size();
for (int i = 0; i < n; i++) {
int idx = word[i] - 'a';
if (curr->children[idx] == NULL) {
// create new node when neccessary (wasn't created before)
curr->children[idx] = new TrieNode();
}
curr = curr->children[idx];
}
// mark that this is a word
curr->isWord = true;
}
bool search(string word) {
TrieNode *curr = root;
int n = word.size();
for (int i = 0; i < n; i++) {
int idx = word[i] - 'a';
if (curr->children[idx] == NULL) {
// when there isn't a word
return false;
}
curr = curr->children[idx];
}
// if this is a word
return curr->isWord;
}
bool startsWith(string prefix) {
TrieNode *curr = root;
int n = prefix.size();
for (int i = 0; i < n; i++) {
int idx = prefix[i] - 'a';
if (curr->children[idx] == NULL) {
return false;
}
curr = curr->children[idx];
}
// similar as search() but it doesn't have to be a word,
// just need to BE there without facing any NULL
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/