Programming Assignment 1: WordNet
題目地址:http://coursera.cs.princeton.edu/algs4/assignments/wordnet.html
1. 題目閱讀
WordNet定義
WordNet是指一個包含唯一根的有向無環圖,圖中每一組詞表示同一集合,每一條邊v→w表示w是v的上位詞。和樹不同的地方是,每一個子節點可以有許多父節點。
輸入格式
- 同義詞表
文件中每行包含一次同義名詞。首先是序號;然後是詞,用空格分開。若為詞組,則使用下劃線連接詞組。最後是同義名詞的註釋
36,AND_circuit AND_gate,a circuit in a computer that fires only when all of its inputs fire
- 上位詞表
文件中包含序號i的上位詞j。若有多個上位詞,則使用空格分隔。
34,47569,48084
WordNet數據類型
需要實現
- 構造函數,通過同義詞表和上位詞表
- 叠代器
- 判斷詞是否在WordNet裏
- 計算兩個詞的最短祖先路徑距離
- 計算兩個詞的最短祖先路徑
最短祖先路徑是指兩個點v、w到達相同點距離和最短的點x。
另外,還可以給定兩個集合A、B,兩個集合中的各自擁有一個點v、w到達相同點距離和最短的點,對比第一種,還需要從集合中找出合適的v、w。
SAP數據類型(最短祖先路徑)
需要實現
- 構造函數
- 求兩點的最短祖先編號、距離
- 求兩集合的最短祖先編號、距離
Outcast detection
給定一串詞,給出哪個詞和其他詞最不相關
2. 題目分析
按照我認為的實現順序分析
SAP實現
構造函數:構造digraph
祖先編號,路徑: 尋找兩個點v、w到達相同點距離的最短點x。
第一步,對v、w進行BFS搜索,找到從v、w到其他點的最短距離。BFS是O(E + V)
第二步,將v、w到相同點的距離相加,若其中一個點不能到達,則這個點的最短祖先距離為-1。在這個遍歷過程中,找到相加距離最短的點則為最短祖先距離。O(V)
整個算法性能:O(E + V)
卡在這裏了一會,主要是讀題目的checklist時候看到bfs當成深度優先了,然後思想就被禁錮dfs了
兩個集合的最短祖先
兩個集合兩兩求,找最小。感覺這個肯定超時了。但是感覺也只能這樣。暫時用這個方法寫。
正確實現方法:BFS提供使用一個集合作為參數構造BFS的,得到的是點到集合的最短距離,由於不需要輸出路徑,這裏你可以認為一個集合就是一個點,就可以按照上面的方法來計算兩個集合的最短祖先了。
WordNet實現
構造函數:文件讀取,使用java的string分割。然後構造一個digraph。
關於文件存儲
這裏的輸入都是string,不是序號,需要先將單詞對應為序號。
構造一個類存儲同義詞集合,包括序號和單詞。,第一句是錯的,不需要構造這個,因為這裏不需要知道一個序號下面有什麽單詞。第二句也是錯的,因為sap的輸出需要輸出單詞,還是需要構造一個map存序號和單詞的關系。但是api只輸出一個單詞,不懂為什麽。這裏api是要輸出那一串用空格分開的詞。
同義詞組:使用一個map存儲單詞所對應的序號。這裏求出最大的序號,就知道digraph有多少個頂點,可以構造空digraph。
上位詞關系:使用一個digraph存儲
叠代器:返回map的key的叠代器
最短祖先路徑、距離:調用sap
邊界條件:判斷是否有環,調用DirectedCycle類。判斷是否有多個root,如果一個點有一個出的邊,則不是root。
Outcast detection
構造函數:因為需要immutable,要拷貝WordNet。暫時先不考慮這個,直接引用參數裏的wordnet。
上面直接引用沒啥問題。java的immutable還是沒太搞懂
outcast:計算每個輸入詞和其他詞的距離,輸出最大的
3. 第一次提交的問題
corner case的異常拋出不全
叠代器裏有null的沒考慮,isnoun參數為null沒考慮
WordNet的sap返回值錯誤
應該返回所有的詞,用空格分開,跟輸入一樣的方式,而不是只返回一個詞。
集合的最短祖先求解超時
果然超時了。參考了別人的博文,直接使用BFS好像是不行的,需要自己實現才能解決時間。決定自己寫了。
準備自己寫BFS時,發現作者提供的BFS是有點到集合的最短距離的構造方法,用這個就可以。分析已經寫在上文
4. 性能優化
參考
1.Programming Assignment 1: WordNet
Programming Assignment 1: WordNet