--- title:2023 年資訊科技產業專案設計課程 作業二 --- # 2023「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2023)」作業二 >#### 貢獻者:鋒美食-Tastii >🗿:interviewer >🤓:interviewee > >#### 影片 >* [鋒美食-Tastii: Homework2 (漢)](https://youtu.be/9I0261Ts0kU) ### 46. [Permutations](https://leetcode.com/problems/permutations/) 🗿:(開場...) 🗿:你知道我們公司最核心業務資料探勘,我想要你設想一個情境 🗿:假設今天你拿到一份dataset,裡面有100多筆features,你有一些先備知識讓你能夠從這些features中提取出你認為比較有用用處的特徵,而有時候要建立一些機器學習模型訓練時,要先將某些特徵的權重給設定,我希望你可以先簡單想一個方法快速將這些特徵的優先順序給定出 🤓:根據Oscar你的說法,我已經將所需要的feature都提取出來了 🤓:那其實我首先要做的就是排列出這些已經選取出來的feature 🤓:請問我可假設這些資料是1~n的整數,以代替特徵名稱嗎? 🗿:沒有問題 🤓:假設擷取出來的特徵為[1,2,3],那我會獲得的排列順序就是 * [1,2,3]、[1,3,2]、[2,1,3]、[2,3,1]、[3,2,1]、[3,1,2] 🤓:這樣我打算直接實作排列 🤓:首先排列最開始想到的就是用Recursive的方法進行 🤓:先假設所有我需要的特徵都存在一個nums vector中,之後輸出排列結果會存在二維result vector中 🤓:然後我要使用swap的方法,我需要一個for loop每次交換nums中其中兩個元素位置 🤓:例如以上面[1,2,3]為例子,我在loop中會產生[1,2,3]是由nums[0]和nums[0]交換位置的結果、[2,1,3]是由nums[0]和nums[1]交換位置的結果、[3,2,1]是由nums[0]和nums[2]交換位置的結果,3種排列 🤓:而在這些排列中我也必須去swap他們元素中的位置,所以這邊用到recursive,在上面的loop中從nums[0]為起點去和後面的元素交換位置,而進到resursive後,我則變成由nums[1]開始往後去交換,所以進到recursive後起始的交換位置就+1,這很合理因為看前面例子產生的3種結果,開頭分別是1、2、3,所以我往後的交換就不考慮開頭的元素 ![](https://hackmd.io/_uploads/HJzFIk--T.png) ```cpp= void permutateRecursive(vector<int> &nums, int begin, vector<vector<int>> &result){ for(int i = begin ; i < nums.size() ; i++){ swap(nums[begin],nums[i]); permutateRecursive(nums,begin+1,result); swap(nums[begin],nums[i]); // * } } ``` 🤓:最後一個swap我標註*號的地方,這邊要再將剛剛swap過的元素換回來,這樣後續才不會錯亂掉 🤓:然後我還必須要有終止條件,也就是把排列好的結果存起來 ```cpp= void permutateRecursive(vector<int> &nums, int begin, vector<vector<int>> &result){ if(begin >= nums.size()-1){ result.push_back(nums); return; } for(int i = begin ; i < nums.size() ; i++){ swap(nums[begin],nums[i]); permutateRecursive(nums,begin+1,result); swap(nums[begin],nums[i]); // * } } ``` 🤓:最後呼叫該程式,並把結果存起來 ```cpp= vector<vector<int>> permute(vector<int>& nums) { vector<vector<int>> result; permutateRecursive(nums,0,result); return result; } ``` 🗿:我覺得你解釋的蠻清楚的,那我想和你探討一下這方法的缺點 🗿:先請你分析一下這方法的時間空間複雜度 🤓:時間複雜度是O(n!*n),因為有n!個排列結果,而每次要將一個排列結果存入result需要花費O(n)的時間 🤓:空間複雜度是O(n!),因為有n!個排列結果要存 🗿:那排列過後的結果有n!種,你這種方法是 Full Search,在訓練模型的時候是不可能把n!都訓練一次來比較結果的,那請問你有沒有方法可以降低訓練次數的 🤓:(thinking...) 🤓:那一樣假設我已經挑出了一些有用的feature,但我還想要從這些feature中更進一步的篩出哪些才是真正有用的 🤓:我一樣想用greedy的方法把這些feature 測試過一輪,但我又要大幅減少訓練模型的次數 🤓:首先我先設定一個模型訓練合格分數為best,再來從我挑出來的features中選一個或是隨機一個放到一個result集合中,接著,使用result中的的特徵和全部features中排序第二的特徵訓練一個模型用交叉驗證計算出分數 🤓:如果模型的結果優於前面best,則將這個排序第二的feature放入result集合中,並將best更新 🤓:後面則不斷重複上面動作直到所以features都測驗完成 🤓:這樣我就可以更進一步挑出更好的features 🤓:然後從這些更優良的features的集合result中,我再做回歸分析找出最佳權重 🗿:喔ok,那這方法明顯比一開始的permutation好上許多 🗿:(ending...) ### 作業二 初步檢討 & 改進 #### interviewer side * 題目設計還有待加強 #### interviewee side * 因為想要和permutate扯上關係,題目設定有點奇怪,其實大可以跳過前面實做permutate的部分,直接進行後半段就好。 * 之後試試看用C寫 * 畫圖舉例的時候我想表達的是nums[0]nums[1],但是我用的例子又是數字1 2 3,這樣解釋起來很容易混淆,舉例失當,我應該將例子用A B C 去帶,這樣會好很多 * 最後一段口頭說明的部分其實也可以在google document上畫圖出來說明 ### 作業二 我給其他學員評價 * 主要觀察REACTO有沒有做到 * 題目與答案是否合理,例如我有發現一個人的題目基本上是經典sort的變形,但他解答時卻直接使用C++ stl的sort來解