---
# System prepended metadata

title: 演算法 HW7
tags: [演算法]

---

# 演算法 HW7

## :book: 觀念題 

### 第一題 knapsack problem背包問題(Ch3)
有四件物品，編號由1到4，物品重量依序為20,40,10,30。物品價值依序為100,60,30,60。背包最大限重為80。請說明要放哪些東西(可以放部分)，可以讓背包內物品價值總合最大。

* ans
    1: 100/20=5
    2: 60/40=1.5
    3: 30/10=3
    4: 60/30=2
    東西 : 1號 (20) 2號(20) 3號(10) 4號(30)
    價值 : 5 * 20 + 3 * 10 + 2 * 30 + 1.5 * 20 = 100 + 30 + 60 + 30 = 220
    總重 : 80

### 第二題 Closest Pair Problem
請說明Closest Pair Problem，每回合的合併過程？(可參考PPT13頁)

* ans
    1. 先進行排序 → 較容易找出需要做比較的點
    2. 若只有一個點 → 距離為無限大
    3. 找出中線L，分兩等分(S_L，S_R)，不斷分割每群只剩一個點
    4. 找出每群最短距離(d_L，d_R)，算出d=min(d_L,d_R)
    5. 有一點P其x值介於L-d和L之間，其y表示為yp，並找出所有所有介於L和L-d以及yp-d和yp+d之間的點。若找到一點和P的距離小於d，則將d值改為此距離。
        ![](https://i.imgur.com/9Fc5U3y.png)
 
### 第三題 Convex Hull Problem
請說明Convex Hull Problem，
(1)為何不直接用sort來得到polygon，而要採用merge？
(2)請說明如何將polygon，修改成convex hull？

:::success

給定一平面上的點集合，找出一個最小的凸多邊形可以包含所有的點。 
1.先找出多邊形(sort or merge)
2.找凸多邊形(reflex angle)
    ![](https://i.imgur.com/3uV4Rfe.png)
:::
* ans
    * 第一題
        因為merge的時間複雜度<sort的時間複雜度
        * sort : 將向量角度做排序，即可得到一個多邊形。而排序的間複雜度至少為nlogn，若選擇排序，會使時間複雜度變得更大。
        * merge : 左邊的凸多邊形的點順序不變，接著先找出右邊凸多邊形的最高及最低的點，此兩點可把一個凸邊行切成左右兩邊，左邊的順序為順時針，右邊為逆時針。因此會得到三組以排序好的序列。再將此三組序列進行merge即可得到一個多邊形。(依照向量)
    * 第二題
        檢查每一個點的內角是否超過180度(reflex angle)，若有超過，則將該點刪除。(Graham scan)
##  :desktop_computer: 程式題 Divide and Conquer (使用語言 : C++)

### 第四題 將linked list的數列排序

* leetcode 148
* 時間:20分鐘
* 自己完成的程度 : 參考網路
* 思路 : 
:::success
1.先放入vector內，在進行sort，再放進list內進行回傳。
2.使用merge sort進行排序。
:::
* 程式碼 : 
    * vector
    ```cpp==
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            vector<int> nums;
            ListNode* temp=head;
            while(temp)
            {
                nums.push_back(temp->val);
                temp=temp->next;
            }
            sort(nums.begin(),nums.end());

            ListNode* ans=new ListNode;
            ListNode* answer=ans;
            for(int i=0;i<nums.size();i++)
            {
                ans->next=new ListNode(nums[i]);
                ans=ans->next;
            }
            return answer->next;
        }
    };
    ```
    * merge sort
    ```cpp==
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            // 是空的list或是只有一個，直接回傳
            if(head==NULL || head->next==NULL)
                return head;
            ListNode *temp=head,*slow=head,*fast=head;
            // 使用兩個指標，一個一次前進一個，一個一次前進兩個
            // 當快指標走到最後的時候，慢指標會剛好走到中間
             while (fast && fast->next) 
             {
                 temp=slow;
                 slow=slow->next;
                 fast=fast->next->next;
             }
            // 此時，slow剛好到中間
            temp -> next = NULL;  //斷開
             return Merge(sortList(head), sortList(slow));
        }
        //Merge Sort
        ListNode* Merge(ListNode *L1,ListNode *L2)
        {
            ListNode* t1=new ListNode;
            ListNode* t2=t1;
            while(L1 && L2)
            {
                if(L1->val<L2->val)
                {
                    t2->next=L1;
                    L1=L1->next;
                }
                else
                {
                    t2->next=L2;
                    L2=L2->next;
                }
                t2=t2->next;
            }

            if(L1)
                t2->next=L1;
            if(L2)
                t2->next=L2;
            return t1->next;
        }
    };
    ```
* 通過截圖
    * vector
        ![](https://i.imgur.com/WvzdX4z.png)
    * merge sort
        ![](https://i.imgur.com/UMmv8gy.png)

### 第五題 將排序好的數列轉為二元搜尋樹

* leetcode 108
* 時間:15分鐘
* 自己完成的程度：靠自己
* 思路 : 
:::success
因已知依排序好數列，因此只須將此數列一值分割成兩等分，並將其中間值訂為root，直到數列全被巡過。
:::
* 程式碼:

```cpp==
/**
 * 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* sortedArrayToBST(vector<int>& nums) {
        return solve(nums,0,nums.size()-1);
    }
    TreeNode* solve(vector<int> &nums,int head,int tail)
    {
        if(head>tail)
            return NULL;
        
        int mid=head+(tail-head)/2;
        
        TreeNode* temp=new TreeNode;
        temp->val=nums[mid];
        
        temp->left=solve(nums,head,mid-1);
        temp->right=solve(nums,mid+1,tail);
        
        return temp;
    }
};
```
* 通過截圖
    ![](https://i.imgur.com/HcFhzZK.png)
### 相關題(自由作答)
* leetcode 109
* 時間:15分鐘
* 自己完成的程度：靠自己
* 思路 : 
:::success
先將提供的list轉為vector。
因已知依排序好數列，因此只須將此數列一值分割成兩等分，並將其中間值訂為root，直到數列全被巡過。
:::
* 程式碼:
```cpp==
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
/**
 * 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* sortedListToBST(ListNode* head) {
        ListNode *temp=head;
        vector<int> nums;
        while(temp)
        {
            nums.push_back(temp->val);
            temp=temp->next;
        }
        return solve(nums,0,nums.size()-1);
    }
    TreeNode* solve(vector<int> &nums,int head,int tail)
    {
        if(head>tail)
            return NULL;
        
        int mid=head+(tail-head)/2;
        
        TreeNode* temp=new TreeNode;
        temp->val=nums[mid];
        
        temp->left=solve(nums,head,mid-1);
        temp->right=solve(nums,mid+1,tail);
        
        return temp;
    }
};
```
* 通過截圖
    ![](https://i.imgur.com/4nIxfjo.png)

## :pushpin:心得

### 第六題 本週心得
遞迴之前一年級就有碰過了，但沒有學得很好，所以本次在寫程式題的時候有點吃緊，希望可以越來越熟悉。

###### tags: `演算法`