meyr543
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    2
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Leetcode刷題學習筆記--Tree Traversal ## Introduction ref : [Tree Traversals (Inorder, Preorder and Postorder)](https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/) ![binary tree](https://media.geeksforgeeks.org/wp-content/cdn-uploads/2009/06/tree12.gif) 1. pre-order 順序 : parent -> left -> right, 從top -> bottom ==適用於要先決定好parent才可以決定child。== **1->2->4->5->3** ![](https://i.imgur.com/tVUSfz6.png) 2. in-order 順序 : left child -> parent -> right child, 從bottom ->top **4->2->5->1->3** ![](https://i.imgur.com/pasfqjy.png) ==在binary search tree(BST)中,使用inorder可以得到由小到大的排序。== 3. post-order 順序 : left child -> right child -> parent, 從bottom -> top ==適用於要先決定好child才可以決定parent== **4->5->2->3->1** ![](https://i.imgur.com/NHMcYc3.png) 4. level-order(BFS) ![binary_tree_traversal](https://leetcode.com/problems/validate-binary-search-tree/Figures/145_transverse.png) ## Problems ### [653. Two Sum IV - Input is a BST](https://leetcode.com/problems/two-sum-iv-input-is-a-bst/) 給定一個target,找出在BST中是否有兩個node加起來為target。 想法: 1. 把node全部讀出來放入unordered_set 2. 如果不用額外的空間,只在tree中尋找。(下面code的解法),這個也算是DFS的==pre-order==尋訪。如果是balanced binary tree則效率為O(logN) ```cpp= TreeNode* findNode(TreeNode *root, int val) { if(!root) return nullptr; if(root->val == val) return root; if(val > root->val) return findNode(root->right, val); else return findNode(root->left, val); } bool helper(TreeNode* root, TreeNode* curr, int k) { TreeNode* target; if(!curr) return false; target = findNode(root, k - curr->val); if(target && target != curr) return true; else return helper(root, curr->left, k) || helper(root, curr->right, k); } bool findTarget(TreeNode* root, int k) { if(!root) return false; return helper(root, root, k); } ``` ### [199. Binary Tree Right Side View](https://leetcode.com/problems/binary-tree-right-side-view/) 給一個binary tree只輸出最右邊的value。典型的==level-order traversal==。 ```cpp void helper(vector<TreeNode *>& q, vector<int>& rtn) { if(q.size() == 0) return; vector<TreeNode *> newq; for(TreeNode *node : q) { if(node->left) newq.push_back(node->left); if(node->right) newq.push_back(node->right); } rtn.push_back(q.back()->val); helper(newq, rtn); } vector<int> rightSideView(TreeNode* root) { if(!root) return {}; vector<int> rtn; vector<TreeNode *> q; if(root->left) q.push_back(root->left); if(root->right) q.push_back(root->right); rtn.push_back(root->val); helper(q, rtn); return rtn; } ``` ### [1008. Construct Binary Search Tree from Preorder Traversal(Medium)](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/) 給你一個用preorder排序過的vector,根據這個vector重建binary tree。 > 1. 第一個數值一定是root > 2. 因為binary tree的特性是右邊的數值一定大於root,所以找出比第一個數值大的分界點。 > 3. 利用recursive來產生左右邊的sub-tree。 > ps: 可以用使只傳遞上下邊界來改善效能。 ```cpp= TreeNode* bstFromPreorder(vector<int>& preorder) { auto n = preorder.size(); if(n == 0) return nullptr; else if(n == 1) return new TreeNode(preorder[0]); else { auto pos = upper_bound(preorder.begin() + 1, preorder.end(), preorder[0]); vector<int> left(preorder.begin() + 1, pos); vector<int> right(pos, preorder.end()); return new TreeNode(preorder[0], bstFromPreorder(left), bstFromPreorder(right)); } } ``` ### [617. Merge Two Binary Trees(Easy)](https://leetcode.com/problems/merge-two-binary-trees/) 給你兩個binary tree, 如果位置一樣的node兩個tree都有,就把node的數值相加,不然就是取有的那個node。 > 1. 重複使用node,避免新增node。 > 2. 把數值都往root1加。 > 3. ==取root->left或root->right的時候,要先判斷root是否為null。== ```cpp= TreeNode* helper(TreeNode *root1, TreeNode *root2) { if(!root1 && !root2) return nullptr; else if(!root1) return root2; else if(!root2) return root1; else { root1->val += root2->val; return root1; } } TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) { TreeNode *newroot = helper(root1, root2); if(newroot) { newroot->left = mergeTrees( root1 ? root1->left : nullptr, root2 ? root2->left : nullptr); newroot->right = mergeTrees( root1 ? root1->right : nullptr, root2 ? root2->right : nullptr); } return newroot; } ``` ### [1026. Maximum Difference Between Node and Ancestor(Medium)](https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/) 給你一個binary tree,找出任一node和parent最大的差值。 > 1. 不是一個BST,所以最大最小值不是最頂點的node。 > 2. ==因為差值是取abs,所以必須紀錄最大最小值。== ```cpp= int helper(TreeNode *node, int maxv, int minv) { if(!node) return -1; int rtn = max(abs(maxv - node->val), abs(minv - node->val)); // 紀錄一路過來的最大最小值。因為差值是取abs maxv = max(maxv, node->val); minv = min(minv, node->val); return max(rtn, max(helper(node->left, maxv, minv), helper(node->right, maxv, minv))); } int maxAncestorDiff(TreeNode* root) { return max(helper(root->left, root->val, root->val), helper(root->right, root->val, root->val)); } ``` ### [572. Subtree of Another Tree(Easy)](https://leetcode.com/problems/subtree-of-another-tree/) 給你兩個binary tree(root, subRoot),判斷root中是否有subtree和subRoot一樣。 > 1. 問題如果是問兩顆tree一不一樣,問題就簡單多了,只要用下面的isSameTree()來判斷。 > 2. 但是問題是問在root中的subtree,所以尋訪整個tree,如果第一的node數值一樣,就使用isSameTree()來判斷是不是一樣。 ```cpp= bool isSameTree(TreeNode *root, TreeNode *subRoot) { if(!root && !subRoot) return true; else if(!root || !subRoot) return false; else { if(root->val == subRoot->val) return isSameTree(root->left, subRoot->left) && isSameTree(root->right, subRoot->right); else return false; } } bool isSubtree(TreeNode* root, TreeNode* subRoot) { if(!root) return false; else if(isSameTree(root, subRoot)) return true; else return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); } ``` ### [1022. Sum of Root To Leaf Binary Numbers(Easy)](https://leetcode.com/problems/sum-of-root-to-leaf-binary-numbers/) 給你一個binary,從root到leaf可以表示成一個binary數值,求出所有binary數值的和。 > 1. 所有進入helper()退出來的時候必須把原本加進去的數值退掉。 ```cpp= void helper(TreeNode *root, int& sum, int& cur) { cur = (cur << 1) + root->val; if(!root->left && !root->right) { sum += cur; return; } if(root->left) { helper(root->left, sum, cur); cur = cur >> 1; } if(root->right) { helper(root->right, sum, cur); cur = cur >> 1; } } int sumRootToLeaf(TreeNode* root) { int sum{0}, cur{0}; helper(root, sum, cur); return sum; } ``` ### [236. Lowest Common Ancestor of a Binary Tree(Medium)](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/) 給你一個binary tree和兩個node(p, q)。找出p, q共同最低的祖先node。 > 1. 如果root為共同的祖先,則可以在左半邊和右半邊找到p或q。 ![](https://i.imgur.com/FHWziiq.png) > 2. 如果root不為共同祖先,則只會在一邊找到p和q,另一邊找不到。那就往non-null的那邊繼續找。 ![](https://i.imgur.com/kUOJHxZ.png) ```cpp= TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { // 找到p或q, return node if(!root || root == p || root == q) return root; // 左邊是否有p或q TreeNode *left = lowestCommonAncestor(root->left, p, q); // 右邊是否有p或q TreeNode *right = lowestCommonAncestor(root->right, p, q); // 左右邊都有,所以這是共同的root if(left && right) return root; // 否則選有的那一邊 return left ? left : right; } ``` 2022/07/05 > 1. 為什麼這題是使用post-order? > 2. 因為我==必須先知道child的狀態==,才可以決定parent是不是LCA。 2024/02/09 還是參考了之前的解答。 ```cpp= TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root || root == p || root == q) return root; // child狀態 TreeNode* l = lowestCommonAncestor(root->left, p, q); TreeNode* r = lowestCommonAncestor(root->right, p, q); // 得到兩邊child狀態之後再來判斷 if(l && r) return root; else return l ? l : r; } ``` ### [968. Binary Tree Cameras](https://leetcode.com/problems/binary-tree-cameras/) 一台camera可以看到自己和上下的node,試問最少的camera可以覆蓋所有的node。 > 1. 一個node有三種狀態,放置camera,有被camera監視,沒有被camera監視。 > 2. 如果top-down,就必須考慮node的所有可能,還要根據root node狀態推斷child node可能的狀態,比較困難。 > 3. 如果bottom-up的話,因為bottom狀態確定了,比較容易推斷root node的狀態,所以使用bottom-up。 > 4. 既然是bottom-up,就是post-order,先走訪到最底部才開始判斷前一個的狀態。 ```cpp= class Solution { enum state {mon, nomon, camera}; int cnt; int helper(TreeNode *root) { if(!root) return mon; // 把null node視為monitor node,因為不用管他 int l = helper(root->left); int r = helper(root->right); if(l == nomon || r == nomon) { // child有一個沒被monitor, 放置camera, case1 cnt++; return camera; } else if(l == mon && r == mon) // case2 return nomon; return mon; // child 有一個有camera, case 3 // left, right // mon, mon case 2, leaf // mon, nomon case 1 // mon, camera case 3 // nomon, mon case 1 // nomon, nomon case 1 // nomon, camera case 1 // camera, mon case 3 // camera, nomon case 1 // camera, camera case 3 } public: int minCameraCover(TreeNode* root) { int val = helper(root); return (val == nomon ? 1 : 0) + cnt; // 因為root沒被monitor,所以放置一個camera // time complexity : O(N) // space complexity : O(N) } }; ``` ### [199. Binary Tree Right Side View(Medium)](https://leetcode.com/problems/binary-tree-right-side-view/) 列出一個binary tree每個level最右邊node的數值。 > 1. 使用preorder traversal,但是先走訪右邊再走訪左邊。因為我們想要先拿到右邊的node。 > 2. 使用level來記錄目前走到的level,因為每一層只有一個right-most node,所以當rtn.size() < level我們才紀錄。 ```cpp= class Solution { void helper(TreeNode *root, int level, vector<int>& rtn) { if(!root) return; if(rtn.size() < level) rtn.push_back(root->val); helper(root->right, level + 1, rtn); helper(root->left, level + 1, rtn); } public: vector<int> rightSideView(TreeNode* root) { vector<int> rtn; helper(root, 1, rtn); return rtn; } }; ``` ### [110. Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) 判斷binary tree是否為balanced。balanced的定義為從root來看左子樹和右子樹的高度差不為1。 > 1. 因為要先知道左右兩邊的高度,所以為post-order。 > 2. 得到兩邊子樹的高度之後,如果不是balanced那就不需要再判斷直接回傳-1。 > 3. 如果兩邊差大於1也是回傳-1。 > 4. 最後回傳計算後的高度。 ```cpp= int helper(TreeNode *root) { if(!root) return 0; int hofl = helper(root->left); int hofr = helper(root->right); if(hofl == -1 || hofr == -1 || abs(hofl - hofr) > 1) return -1; return max(hofl, hofr) + 1; } bool isBalanced(TreeNode* root) { return helper(root) == -1 ? false : true; } ``` ### [437. Path Sum III](https://leetcode.com/problems/path-sum-iii/) 找到在binary tree中的path剛好總合為target。這邊的path的定義是從parent到child。不會有child->parent->child的路徑。 > 1. 每個node都可以為起始點,所以使用line 13, line 14,把path總和算是每個node的起點。 > 2. 使用helper來計算以root為起點的path總和。 > 3. 在helper中經過的每個node都為終點,所以計算總合。line 3。 > 4. 如果以這個點的總和為target則加1,line 4。 > 5. 繼續統計以root->left和root->right為終點的path。line 5,6。 > 6. 因為有line 13, 14,所以不必計算單點是否等於target。 ```cpp= int helper(TreeNode *root, long pre) { if(!root) return 0; long cur = pre + root->val; return (cur == target) + helper(root->left, cur) + helper(root->right, cur); } int target; int pathSum(TreeNode* root, int targetSum) { if(!root) return 0; target = targetSum; return helper(root, 0) + pathSum(root->left, targetSum) + // 從 root->left開始,所以不用判斷每個點是否為traget pathSum(root->right, targetSum); // 從 root->right開始 } ``` ### [2246. Longest Path With Different Adjacent Characters](https://leetcode.com/problems/longest-path-with-different-adjacent-characters/description/) 找出tree中,最長的path其中每兩個相鄰的node的char都不一樣。 > 1. 一開始使用了DFS結果TLE。 > 2. 參考了lee215大的解法,發現這題和[124. Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/)蠻像的。 > 3. 應該說只要是在tree中找path應該都是一樣的套路。 > 4. path至少會有一個node, > 5. 兩個以上的node就是會跟child連在一起。 > 6. 有可能跟一個child連在一起,也有可能跟兩個child連在一起。 > 7. 如果是跟兩個child連在一起。那一定是最長的兩個child。 > 8. why preorder? 因為必須先知道每個child最長的path。 > 9. 根據s[cur] != s[child],才可以判斷要不要取用這條path。所以判斷必須在pre-order之後。 > 10. 回傳只能傳回node + 最長的child。 ```cpp class Solution { // why pre-order? // 因為必須先知道每個child的最長path, // 根據s[cur] != s[child],才可以判斷可不可以取用這條path, // 必須取出兩條最長的child path就可以拼成更長的Path int maxans{0}; int dfs(unordered_map<int, vector<int>>& m, int cur, string& s, int len) { int big1{0}, big2{0}; for(auto& child : m[cur]) { int rtn = dfs(m, child, s, len + 1); // 從目前node往下的path長度 if(s[cur] == s[child]) continue; if(rtn > big2) big2 = rtn; if(big2 > big1) swap(big1, big2); } maxans = max(maxans, big1 + big2 + 1); // 經過node最長的path由node和兩個最長的邊組成 return big1 + 1; // 最長一條path } public: int longestPath(vector<int>& parent, string s) { unordered_map<int, vector<int>> m; // node, adj node for(int i = 1; i < parent.size(); ++i) m[parent[i]].push_back(i); dfs(m, 0, s, 0); return maxans; } }; ``` ### [958. Check Completeness of a Binary Tree](https://leetcode.com/problems/check-completeness-of-a-binary-tree/description/) 給你一個TreeNode* root,試判斷是否為complete binary tree。 > 1. 一開始一直在想到底是要用pre-order, in-order或是post-order,就是忘了想用level order。 > 2. 另一個解法是把每個node都給上一個value,最後排序這個vector但是會int overflow。 > 3. 根據 complete binary tree的特性,如果我用level order traversal,就不會在node之前先遇到nullptr。 > 4. 如果是complete binary tree最後的queue內容都會是nullptr。 ```cpp= bool isCompleteTree(TreeNode* root) { queue<TreeNode*> q{{root}}; // 遇到nullptr就停止。 while(q.front() != nullptr) { TreeNode* cur = q.front(); q.pop(); q.push(cur->left); q.push(cur->right); } // 如果是complete binary tree的話,最後都會是nullptr while(!q.empty() && q.front() == nullptr) q.pop(); return q.empty(); } ``` ### [979. Distribute Coins in Binary Tree](https://leetcode.com/problems/distribute-coins-in-binary-tree/description/) binary tree中每個node都有不同的coins,找出最少的移動可以使每個node都有一個coin。 > 1. 參考官方解答。 > 2. why post-order traversal? > + 必須知道需要往child移動多少的coins,或是必須知道要從child移動多少coins上來parent。 > + 正數表示child有多的coins必須移動上來。 > + 負數表示child有少,必須從parent動到child。 > 3. 因為child移動到child都要經過parent,所以可以視為多的先從child移動到parent,parent再分配給child。 > 4. 也就是parent是一個中央統籌單位,多的coins先交給中央parent,再由中央parent分配給不夠的child。 > 5. 如果整體來說還是不夠,中央parent再跟更上面的parent要求更多的coins。 > 6. 如果分配完了還有多出來,中央parent再把剩下的往更上的parent繳交出去。 ```cpp= class Solution { int ans{}; // child多的coin,必須從child移動到root // child缺的coin, 必須從root移動到child int dfs(TreeNode* root) { // + : child->root, - : root->child if(!root) return 0; int l = dfs(root->left); int r = dfs(root->right); ans += abs(l) + abs(r); return root->val + l + r - 1; } public: int distributeCoins(TreeNode* root) { dfs(root); return ans; } }; ``` ### [2477. Minimum Fuel Cost to Report To the Capital](https://leetcode.com/problems/minimum-fuel-cost-to-report-to-the-capital/description/) 每個node除了0之外,都要往node 0前進,每前進一個node需要1L fuel。一台車子最多有seats個椅子。試問,最少的fuel來讓所有的node都達到node 0。 > 1. 如果有n個人,則需要多少台車子? 使用無條件進位ceil。 ```cpp ceil(n / s); ``` > 2. 所以使用post-order,因為要到達最後的leaf node,再往node 0前進,推算有多少個node在後面。 > 3. 使用vector<int> vis來記錄訪問過的node。 > 4. 為什麼統計每個node的車子數,就是統計需要的fuel? ![image](https://hackmd.io/_uploads/Bk1hKcpSp.png) ```cpp= class Solution { unordered_map<int, vector<int>> adj; vector<int> vis; // 使用visited array來避免重複走 long long ans; int dfs(int n, int s) { vis[n] = 1; int count = 1; //統計從child過來的node有多少個 for(auto& nxt : adj[n]) { if(!vis[nxt]) count += dfs(nxt, s); } if(n != 0) ans += ceil((double)count / s); //站在每個node,會有幾台車經過 // ans += ((rtn + seats - 1) / seats); // 不使用ceil的無條件進位 return count; // 有多少個node } public: long long minimumFuelCost(vector<vector<int>>& roads, int seats) { for(auto& r : roads) { adj[r[0]].push_back(r[1]); adj[r[1]].push_back(r[0]); } vis.resize(roads.size() + 1); dfs(0, seats); return ans; } }; ``` ###### tags: `leetcode` `刷題`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully