Algo_8_BinaryTree
學習算法
構建BinaryTree
- 靜態版二叉樹
- 時間複雜度為O(m),空間複雜度為O(n),因為使用了長度為m的遞歸棧
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
struct Node {
char value;
int lson;
int rson;
} tree[N]; // tree[0]不用表示空節點
int n = 1; // 記錄節點位置
int newNode(char val)
{
tree[n].value = val;
tree[n].lson = 0;
tree[n].rson = 0;
return n++;
}
void insert(int &father, int child, int l_r)
{
l_r == 0 ? tree[father].lson = child : tree[father].rson = child;
}
int dfn[N] = {0};
int dfn_timer = 0;
void dfn_order(int father)
{
if (father != 0)
{
dfn[father] = ++dfn_timer;
printf("dfn[%c].value=%d ", tree[father].value, dfn[father]);
dfn_order(tree[father].lson);
dfn_order(tree[father].rson);
}
}
int visit_time=0;
void visit_order(int father){
if(father != 0){
printf("visit[%c]=%d ",tree[father].value,++visit_time);
visit_order(tree[father].lson);
visit_order(tree[father].rson);
printf("visit[%c]=%d ",tree[father].value,++visit_time);
}
}
int deep[N] = {0};
int deep_timer = 0;
void deep_child(int father){
if(father != 0){
deep[father] = ++deep_timer;
printf("deep[%c]=%d ",tree[father].value,deep[father]);
deep_child(tree[father].lson);
deep_child(tree[father].rson);
--deep_timer;
}
}
int num[N] = {0};
int num_node(int father){
if(father == 0) return 0;
else{
num[father] = num_node(tree[father].lson)+ num_node(tree[father].rson) + 1;
printf("num[%c]=%d ",tree[father].value,num[father]);
return num[father];
}
}
void pre_order(int father){
if(father != 0) {
cout << tree[father].value;
pre_order(tree[father].lson);
pre_order(tree[father].rson);
}
}
void in_order(int father){
if(father != 0) {
in_order(tree[father].lson);
cout << tree[father].value;
in_order(tree[father].rson);
}
}
void post_order(int father){
if(father != 0) {
post_order(tree[father].lson);
post_order(tree[father].rson);
cout << tree[father].value;
}
}
int build_tree(){
int A = newNode('A');int B = newNode('B');int C = newNode('C');
int D = newNode('D');int E = newNode('E');int F = newNode('F');
int G = newNode('G');int H = newNode('H');int I = newNode('I');
insert(E,B,0);
insert(E,G,1);
insert(B,A,0);
insert(B,D,1);
insert(G,F,0);
insert(G,I,1);
insert(D,C,0);
insert(I,H,0);
int root = E;
return root;
}
int main(){
int root = build_tree();
cout << "dfn order: "; dfn_order(root);cout << endl;
cout << "visit order: "; visit_order(root);cout << endl;
cout << "deep child: " ; deep_child(root);cout << endl;
cout << "num of tree: " << num_node(root) << endl;
cout << "in order: " ; in_order(root);cout << endl;
cout << "pre order: " ; pre_order(root);cout << endl;
cout << "post order: ";post_order(root);cout << endl;
return 0;
}
Leetcode 226
- tree的題目大部分都可以直接用dfs完成
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(!root)return 0;
TreeNode* tmp = root->left;
root->left = root->right;
root->right = tmp;
if(root->left) invertTree(root->left);
if(root->right) invertTree(root->right);
return root;
}
};
Leetcode 104
class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
int maxL = maxDepth(root->left);
int maxR = maxDepth(root->right);
return max(maxL,maxR)+1;
}
};
Leetcode 110
- 是否平衡為最後節點個數為深度
class Solution {
public:
int check(TreeNode* root){
if(!root) return 0;
int l = check(root->left);
int r = check(root->right);
if(l == -1 || r == -1 || abs(l-r) > 1) return -1;
return max(l,r)+1;
}
bool isBalanced(TreeNode* root) {
if(!root) return true;
return check(root) == -1 ? false : true;
}
};
Leetcode 543
class Solution {
public:
int check(TreeNode* root){
if(!root) return 0;
int l = check(root->left);
int r = check(root->right);
if(l == -1 || r == -1 || abs(l-r) > 1) return -1;
return max(l,r)+1;
}
bool isBalanced(TreeNode* root) {
if(!root) return true;
return check(root) == -1 ? false : true;
}
};
Leetcode 100
- 是否相同檢查節點值就好,如果一方null另一方還沒,代表不一樣,同時都為null則遍歷結束
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(!p && !q) return true;
if(!p || !q) return false;
if(p->val != q->val) return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
};
Leetcode 101
- 對稱樹將原本root拆成左son和右son,將他們當成兩棵樹後再遍歷
class Solution {
public:
bool check(TreeNode* n1,TreeNode* n2){
if(!n1 && !n2 ) return true;
if(!n1 || !n2) return false;
return n1->val == n2->val && check(n1->left, n2->right) && check(n1->right,n2->left);
}
bool isSymmetric(TreeNode* root) {
return check(root->left,root->right);
}
};
Leetcode 112
class Solution {
public:
bool check(TreeNode* root,int target,int sum){
if(!root) return false;
sum += root->val;
if(!root->left && !root->right){
return sum == target;
}
bool l = check(root->left,target,sum);
bool r = check(root->right,target,sum);
return l || r;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
int sum = 0;
return check(root,targetSum,sum);
}
};
Leetcode 572
- 在check的時候,同時check一邊就行,再用AND判斷
class Solution {
public:
bool check(TreeNode* node,TreeNode* subRoot){
if(node == NULL && subRoot == NULL) return true;
if(!node || !subRoot) return false;
if(node->val != subRoot->val) return false;
return check(node->left,subRoot->left) && check(node->right,subRoot->right);
}
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
if(!subRoot) return true;
if(!root) return false;
if(check(root, subRoot)) return true;
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
};
Leetcode 102
- 遍歷節點的時候將樹扁平化成1維陣列,扁平化的方法則用BFS遍歷樹
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root) return res;
queue<TreeNode* > q;
q.push(root);
while(!q.empty()){
int n = q.size();
vector<int> path;
for(int i =0;i<n;i++){
TreeNode* node = q.front();
q.pop();
if(node -> left != nullptr) q.push(node->left);
if(node -> right != nullptr) q.push(node->right);
path.push_back(node->val);
}
res.push_back(path);
}
return res;
}
};
Leetcode 230
- 將樹扁平化成1D陣列後,排序找到第k小的值
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
vector<int> vc;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int n = q.size();
for(int i=0;i<n;i++){
TreeNode* node = q.front();
q.pop();
if(node->left != nullptr) q.push(node->left);
if(node->right != nullptr) q.push(node->right);
vc.push_back(node->val);
}
}
sort(vc.begin(),vc.end());
return vc[k-1];
}
};
Leetcode 530
- 尋找Node中的最小數中先扁平化成1D陣列後,用tow pointer的方式尋找在2 nodes中的最小值
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
vector<int> vc;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int n = q.size();
for(int i = 0;i<n;i++){
TreeNode* node = q.front();
q.pop();
if(node->left != nullptr) q.push(node->left);
if(node->right != nullptr) q.push(node->right);
vc.push_back(node->val);
}
}
sort(vc.begin(),vc.end());
int i =0;
int j =1;
int ans = INT_MAX;
while(i < j && j != vc.size()) {
ans = min(ans,abs(vc[i]-vc[j]));
i++;
j++;
}
return ans;
}
};
Leetcode 98
- 判斷是符合合題目的二叉搜索樹(BST)
- 題目要求:
- 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.
- 題目要求:
第一種拆判斷值後做中序遍歷
class Solution {
public:
bool slove(TreeNode* root,long small,long big){
if(root == nullptr )return true;
if(root->val <= small || root->val >= big) return false;
return slove(root->left,small,root->val) && slove(root->right,root->val,big);
}
bool isValidBST(TreeNode* root) {
if(!root) return true;
return slove(root,LONG_MIN,LONG_MAX);
}
};
第二種使用stack做中序遍歷
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> q;
TreeNode* prev = nullptr;
while(root != nullptr || !q.empty()){
while(root != nullptr){
q.push(root);
root = root->left;
}
root = q.top();
q.pop();
if(prev != nullptr && root->val <= prev->val)return false;
prev = root;
root = root->right;
}
return true;
}
};
Leetcode 235
- 在BST(二叉搜索樹)上找尋LCA(公共祖先)
- 將root拆成左右子樹,後尋找符合條件的1.右邊一定要大於root 2.左邊一定要小於root
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return root;
if(p->val > root->val && q->val > root->val) return lowestCommonAncestor(root->right,p,q);
if(p->val < root->val && q->val < root->val) return lowestCommonAncestor(root->left,p,q);
return root;
}
};
Leetcode 208
- Trie樹
// 初始化Trie樹的Node,children用來存字母index(a->0,z->25)
class TrieNode {
public:
TrieNode* children[26];
bool isEnd;
TrieNode(){
isEnd = false;
for(int i =0;i<26;i++){
children[i] = nullptr;
}
}
};
class Trie {
public:
TrieNode* root;
Trie() {
root = new TrieNode();
}
// 插入時如果沒有對應的值時(存word的index),建立一個新的節點
void insert(string word) {
TrieNode* node = root;
for(char w : word) {
int index = w - 'a';
if(node->children[index] == nullptr) node->children[index] = new TrieNode();
node = node->children[index];
}
node->isEnd = true;
}
// 查找不斷往tree上的node找,值到遍歷完tree
bool search(string word) {
TrieNode* node = root;
for(char w : word ){
int index = w - 'a';
if(node->children[index] == nullptr) return false;
node = node->children[index];
}
return node->isEnd;
}
// 只要有查找到需要的值就結束,不用遍歷完tree
bool startsWith(string prefix) {
TrieNode* node = root;
for(char p : prefix) {
int index = p -'a';
if(node->children[index] == nullptr) return false;
node = node->children[index];
}
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);
*/
Leetcode 2583
- 使用BFS紀錄每一次的sum,并且preiority_queue使用大到小排列,超過題目要求的k時做pop
class Solution {
public:
long long kthLargestLevelSum(TreeNode* root, int k) {
priority_queue<long long, vector<long long>, greater<>> pq;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int n = q.size();
long long sum = 0;
for(int i=0;i<n;i++){
TreeNode* node = q.front();
q.pop();
sum += node->val;
if(node->left != nullptr) q.push(node->left);
if(node->right != nullptr) q.push(node->right);
}
pq.push(sum);
if(pq.size() > k) pq.pop();
}
return pq.size() < k ? -1 : pq.top();
}
};
Leetcode 2641
- 第一次BFS先計算當前level的總和
- 第二次BFS計算這一層node的總和減去同個parent中node的總和
class Solution {
public:
TreeNode* replaceValueInTree(TreeNode* root) {
if(root == nullptr) return nullptr;
queue<TreeNode*> q;
q.push(root);
vector<int> sum_;
sum_.push_back(root->val);
while(!q.empty()){
int n = q.size();
int sum = 0;
for(int i=0;i<n;i++){
TreeNode* node = q.front();
q.pop();
if(node->left) {
sum += node->left->val;
q.push(node->left);
}
if(node->right){
sum += node->right->val;
q.push(node->right);
}
}
sum_.push_back(sum);
}
// for(auto v : sum_)cout << v << endl;
// twice bfs
q.push(root);
int level = 0;
while(!q.empty()){
int n = q.size();
for(int i = 0;i<n;i++){
TreeNode* node = q.front();
q.pop();
int leftAndRight = (node->left?node->left->val:0)+(node->right?node->right->val:0);
if(node->left){
node->left->val = leftAndRight;
q.push(node->left);
}
if(node->right){
node->right->val = leftAndRight;
q.push(node->right);
}
node->val = sum_[level] - node->val;
}
level++;
}
return root;
}
};