# 演算法導論 HW7 https://hackmd.io/@wang1234/HJMuNhkm2 ## 第1題: knapsack problem背包問題(Ch3) n=4 , M=80 , (p₁ , p₂ , p₃ , p₄)=(100,60,30,60) (w₁ , w₂ , w₃ , w₄)=(20,40,10,30) p₁/w₁ = 100/20 = 5   ⇒ 1 p₂/w₂ = 60/40 = 1.5   ⇒ 0.5 p₃/w₃ = 30/10 = 3   ⇒ 1 p₄/w₄ = 60/30 = 2   ⇒ 1 20×1 + 10×1 + 30×1 + 40×0.5 = 80 <font color=#3535FF>x₁=1 , x₂=0.5 , x₃=1 , x₄=1</font> ## 第2題: Closest Pair Problem ![](https://i.imgur.com/l5Dlwah.png) 以分半的方式將集合S從x=L處分成的S<sub>L</sub>和S<sub>R</sub>, 然後分別計算出他們內部最近點的距離,令其為d<sub>L</sub>和d<sub>R</sub>,再取兩者的最小值設為d, 而後回到分界線x=L處,以位在x=L-d ~ L區塊的點的y值,例如:有一<font color=#008000>P點座標(a,b)</font>, 對應到另半邊<font color=#00A2FF>x=L ~ L+d</font>的區塊,在<font color=#00A2FF>y=b-d ~ b+d</font>內尋找是否有落點,且實際計算其與P點的距離是否小於d; 若是位於x=L ~ L+d區塊的點,則在x=L-d ~ L區塊搜索 將此交界處檢查一遍後便可得到集合S裡最近點的距離 ## 第3題: Convex Hull Problem <font color="DarkGray" class="small">請說明Convex Hull Problem, ![](https://i.imgur.com/mM1fT0f.png) (1)為何不直接用sort來得到polygon,而要採用merge?</font> <b>sort做法: </b>從左側多邊形中心的一p點連線至左右兩多邊形的頂點,依連線的角度進行排序,得到合併後的多邊形 <b>merge做法: </b>在合併後的多邊形的有三項特性, 其一是p點所在的左側多邊形,全部頂點依然維持逆時針方向, 而右側部分則以縱向上的最低點與最高點分為兩半,右半部分也依然維持逆時針方向, 但位於(右側多邊形)左半部分的頂點要變成順時針方向的排序, 依這些特性整理出三個區塊,再進行merge <font color=#00A2FF>因為merge做法的時間複雜度比sort做法的低</font> <font color="DarkGray" class="small">(2)請說明如何將polygon,修改成convex hull?</font> <font color=#00A2FF>將在合併後的多邊形裡,造成reflex angle(反角:內角角度為180°~360°)的節點刪除</font> ## 第4題: 將linked list的數列排序 [148. Sort List](https://leetcode.com/problems/sort-list/) <font color="Black">解題思路: > 主要解題的merge sort程式碼式來自其他網頁 > 有merge_sort和merge兩個函式 > 在merge_sort裡用遞迴的方式將list切分成兩半 > 直到傳入的list(nlst)只剩一個或零個成員(空列表) > 在merge裡則將傳入的兩個list(left,right)比較大小並進行合併</font> ```python= class Solution: def sortList(self, head: ListNode) -> ListNode: def merge(left, right): output = [] while left and right: if left[0] <= right[0]: output.append(left.pop(0)) else: output.append(right.pop(0)) if left: output += left if right: output += right return output def merge_sort(nlst): if len(nlst) <= 1: return nlst mid = len(nlst) // 2 left = nlst[:mid] right = nlst[mid:] left = merge_sort(left) right = merge_sort(right) return merge(left, right) temp=[] while head: temp.append(head.val) head=head.next temp=merge_sort(temp) p=ListNode(0) ans=p for i in temp: p.next=ListNode(i) p=p.next return ans.next ``` ![](https://i.imgur.com/y27Tc6F.png) 花60分鐘,參考: [Converting a list to a linked list](https://stackoverflow.com/questions/31553576/converting-a-list-to-a-linked-list) [【Day25】[演算法]-合併排序法Merge Sort](https://ithelp.ithome.com.tw/articles/10278179) [Python tutorial 20 | Merge Sort (合併排序法)](https://anchi-tang.medium.com/python-tutorial-20-merge-sort-%E5%90%88%E4%BD%B5%E6%8E%92%E5%BA%8F%E6%B3%95-dd3e087898a6) ## 第5題: 將排序好的數列轉為二元搜尋樹 [108. Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/description/) <font color="Black">解題思路: > 因為題目給的是遞增list,所以可以優先選擇位於列表中間的值來加入BST,做為root或parent > 由此便能建構出平衡的BST > 再用遞迴傳入比選到的節點(node)小的部分,以建構左子樹 > 比選到的節點大的部分,則建構右子樹</font> ```python= class Solution: def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: def bst(start,end): if start > end: return None mid=(start + end)//2 root=TreeNode(nums[mid]) root.left=bst(start,mid-1) root.right=bst(mid+1,end) return root return bst(0,len(nums)-1) ``` ![](https://i.imgur.com/mq30ZkL.png) 花40分鐘,抄: [資料結構 - Tree 的介紹(使用Python)](https://newaurora.pixnet.net/blog/post/224703989) [Easy Python Solution](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/solutions/2407334/easy-python-solution/?page=2&languageTags=python3) ## 第6題: 美麗數列 [932. Beautiful Array](https://leetcode.com/problems/beautiful-array/) <font color="Black">解題思路: > 我只有觀察出把奇數與偶數各分一邊,就能分成兩個互不影響的區塊 > 直到去觀摩的Solutions裡的程式碼,才發現只要延續從list分割奇偶數的規則繼續切割,最後再合併便可得到解答</font> ![](https://i.imgur.com/iT5xwNz.png) ```python= class Solution: def beautifulArray(self, n: int) -> List[int]: nums = list(range(1, n+1)) def helper(nums) -> List[int]: if len(nums) < 3: return nums odd = nums[::2] even = nums[1::2] return helper(odd) + helper(even) return helper(nums) ``` ![](https://i.imgur.com/nhFO0r4.png) 花90分鐘,抄: [Python easy solution](https://leetcode.com/problems/beautiful-array/solutions/1676288/python-easy-solution/?languageTags=python3) [Python3 solution with detailed explanation - Beautiful Array](https://leetcode.com/problems/beautiful-array/solutions/644612/python3-solution-with-detailed-explanation-beautiful-array/?languageTags=python3&topicTags=divide-and-conquer) ## 心得 這次的程式題都借助其他資訊或答案才完成,對merge sort、Linked List、Binary search tree,甚至包括遞迴,在觀念不清晰或應用不熟練,導致沒能夠自己寫出解法。