# 演算法 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: `演算法`