---
# System prepended metadata

title: '**演算法作業 HW10**'

---

# **演算法作業 HW10**
<font size=5>**1. 01背包問題**</font>
---
* 已知有六個物品，其價值和重量如下，背包重量限制為34。
![](https://hackmd.io/_uploads/ByERjeUB3.png)
* 仿照課本以tree search來解。
* 請將下圖中的框框中，填入其upper bound與lower bound
![](https://hackmd.io/_uploads/Bk4x3eIH2.png)
Ans：
![](https://hackmd.io/_uploads/HkjGBZISn.png)

<font size=5>**2. A * 解multi-stage shortest path problem**</font>
---
* 請使用A* 找出S到T的最短路徑。請畫出樹狀圖，並標示各點的cost，並註明哪裏分枝不用再繼續尋找了。
![](https://hackmd.io/_uploads/SkezngUSn.png)
Ans：
![](https://hackmd.io/_uploads/SJHl0zLBh.png)


<font size=5>**3. Channel Routing Problem**</font>
---
* 請使用A* 解Channel Routing Problem。
* 本題將原本題目的net 7移除，只剩下7個nets，請找出最少track的安排方式。
![](https://hackmd.io/_uploads/r1JV3xUB2.png)
Ans：
**{ 1, 8 }, { 2, 3 }, { 5 }, { 4, 6 }**
![](https://hackmd.io/_uploads/rJOdH7UB2.png)


<font size=6>**Breadth-First Search**</font>
---

<font size=5>**4. 合併二元樹**</font>
---
[Merge Two Binary Trees - LeetCode](https://leetcode.com/problems/merge-two-binary-trees/)
若節點都存在才需要合併。
如果其中一棵樹沒有節點，就把另一棵樹的節點接上去就好。
參考網上答案，完成時間，一分鐘。
```c++
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        //建一個新的樹比較麻煩，所以直接合併到其中一棵樹上
        //若有其中一棵樹沒有此位置的節點，就直接把有的接上去就好
        if(!root1)
          return root2;
        if(!root2)
          return root1;
        //兩棵樹都有此位置的節點，將值加起來合併
        root1->val+=root2->val;
        root1->left = mergeTrees(root1->left ,root2->left);
        root1->right = mergeTrees(root1->right ,root2->right);
        
        return root1;
    }
};
```
![](https://hackmd.io/_uploads/SyQforLB2.png)


<font size=5>**5. 最深葉子的最低共同祖先**</font>
---
[Lowest Common Ancestor of Deepest Leaves - LeetCode](https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves/)
用BFS下去探訪，紀錄每個點的路徑。
得出最深葉節點後，找出每個最深葉節點路徑的最長共同前綴。
該路徑得出的點就是最低共同祖先。
完全靠自己，完成時間：20分鐘。
```c++
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    //最長共同字串前綴
    string LCP(vector<string>&v)
    {
        string lcp="",shortest=v[0];
        //取出最短字串
        for(int i=1;i<v.size();++i)
        {
            if(v[i].length()<shortest.length())
                shortest=v[i];
        }
        //比較並更新最長共同前綴
        for(int i=0;i<shortest.length();++i)
        {
            for(auto s:v)
            {
                if(s[i]!=shortest[i])
                    return lcp;
            }
            lcp+=shortest[i];
        }
        return lcp;
    }
    TreeNode* lcaDeepestLeaves(TreeNode* root) {
        //在BFS時用map{點,路徑}去紀錄每個點
        //最後得出最深葉子點所有路徑的共同前綴
        //前綴路徑得出的點就是共同祖先
        unordered_map<TreeNode*,string>m;
        queue<TreeNode*> q, temp;
        q.push(root);
        m[root]="";
        while(!q.empty())
        {
            temp = q;
            int n = q.size();
            for(int i=0;i<n;++i)
            {
                TreeNode *r = q.front();
                q.pop();
                string s=m[r];
                if(r->left)
                {
                    q.push(r->left);
                    m[r->left]=s+"0";
                }  
                if(r->right)
                {
                    q.push(r->right);
                    m[r->right]=s+"1";
                }  
            }
        }
        //此時temp裡是最深葉節點
        if(temp.size()==1)
            return temp.front();
        vector<string>v;
        //將所有最深葉節點路徑放入vector
        while(!temp.empty())
        {
            v.push_back(m[temp.front()]);
            temp.pop();
        }
        //得到最長共同前綴
        string s=LCP(v);
        //根據路徑得出最低共同祖先
        for(auto c :s)
        {
            if(c=='0')
                root=root->left;
            else
                root=root->right;
        }
        return root;
    }
};
```
![](https://hackmd.io/_uploads/S1RfWPLHh.png)

<font size=5>**6. 本周心得**</font>
---
這次的題目也不會到很複雜，不過花比較多時間在想優化的方法。

---
若有錯誤歡迎指正
