Depth-first Search深度优先搜索专题4
576. Out of Boundary Paths
思路:這道題目難倒了我。最直接的思路是暴力搜索。要注意的問題1是需要仔細觀察Example2,軌跡不同意思是可以從A點到B點,再從B點到A點也可以,只要step夠用。所以暴力搜索,在(i,j)點在步驟允許范圍內肆意地向4個方向擴散。退出條件是if (i == -1 || j == -1 || i == m || j == n),計數退出。這樣會超時。
我知道該用動態規劃了,但是找不出動態方程。
動態規劃:思路是這樣的。例如輸入為 m=2,n=3,N=3,i=0,j=1
如果走1不就能走出邊界的話,按箭頭走。count+1。因為(0,1)只有一個方向能走出邊界,而且到達(0,1)的路徑只有1條。
接下來考慮走2步能走出邊界的方法。從上圖的位置(0,1)到下圖。
count需要分別加上:2,2,1。解釋如下:
從(0,1)到(0,0)只有一條路徑,(0,0)有2個方向走出邊界,所以count+2;
從(0,1)到(0,2)有1條路徑,(0,2)有2個方向走出邊界,所以count+2;
從(0,1)到(1,1)有1條路徑,(1,1)有1個方向走出邊界,所以count+1。
接下來考慮走3步走出邊界的方法。從上圖(0,0),(1,1),(0,2) 位置開始到下圖。
有3條路徑可以到達(0,1),count+3;
有2條路徑可以達到(0,0),count+2*2;
有2條路徑可以達到(1,2),count+2*2。
最終得總數是17。
用數組dp存儲到達(i,j)有幾條路徑。每次迭代新的newDP[i][j] = dp[i?1][j]+dp[i+1][j]+dp[i][j?1]+dp[i][j+1];dp是上一輪的dp。
我沒完成dp思路,是因為我想的是dp[i][j]表示有多少通過(i,j)能有多少count方向出去,也就是最后的總數。
代碼
210. Course Schedule II
思路:與207. Course Schedule類似,只是記錄下排課順序即可。
332. Reconstruct Itinerary
思路:題目一看,和graph相關,和DFS相關。而且要求返回字母序列小的。構建map,對map的value值排序。一個一個輸出即可。可是要注意:所有的tickets是需要用完的。有些情況下先使用順序小的票,不一定能走完。解決方法:dfs函數返回true,如果能走完的情況。接著遇到了問題2:超時.解決:邏輯寫錯了。
代碼
130. Surrounded Regions
思路:難點是題目理解。我理解的題意是:如果O在矩形最外圈,那么它不會被翻轉為X;如果有和最外圈的O在垂直方向上或者水平方向上相鄰的O,那它也不會被翻轉為X。其余的O被翻轉為X。這樣的話根本用不到DFS、BFS之類的。
實際題目含義是:所有被X包圍的O都翻轉為X。
圖中畫紅色部分的O就是被X包圍的。
圖中就沒有被X完全包圍的O。
BFS思路:在矩形邊上的O肯定沒有被X包圍。在垂直、水平方向上與此O相鄰的O也是不被包圍的。可以先把不被包圍的O替換為#。把邊界的O 遞歸處理完成之后,剩余的O就是需要替換的。
Union-Find思路:將O分為兩組;一組是與dummyNode一組,不改變值的;其他組是需要改變值的。
代碼
98. Validate Binary Search Tree
思路:是否有效二叉檢索樹。DFS的思路。先判斷node是否有效,接著判斷node的左節點是否有效,判斷node的右節點是否有效。只是注意,有效值是一個區間。
代碼
778. Swim in Rising Water
思路:例如輸入如下圖:
t=0
????cost=0
????visited[0][0]=true
????可以選擇的 1,24;
????選擇1,增加耗時1=(1-0)
t=1
????cost+=1
????visited[0][1]=true;
????可以選擇的 2,23
????選擇2,增加耗時1=(2-1)
t=2
????cost+=1
????visited[0][2]=true;
????可以選擇的 3,22
????….一直走到(n-1,n-1)
每一步都選擇最小的,就一定是最小的嗎?不一定,沒有理論支持。那就需要把所有路徑都走一遍。在走的過程中如果發現耗時已經>目前的最小耗時就返回。
結果:超時。
學習1:超時是因為我還沒有看到事物的本質。You can swim infinite distance in zero time。可以在瞬時穿過好多個區塊。例如下圖中。起點時刻就是10,或者說等到t=10才能開始移動。移動的時候,因為9,1,2,0,7都<10<10<script type="math/tex" id="MathJax-Element-1"><10</script>,所以相當于瞬時可以達到這些地方。那就相當于在圖中劃線的周圍找到下一個>10>10的最小值就是下一步要走的區塊。
????可以考慮的思路是用一個優先隊列保存點(i,j)的鄰接節點,值小的排在前面。不斷彈出,不斷加入,直到遇到目標節點。原來題目和代碼之間的翻譯差距是這么大。好神奇!
學習2:在上一個解決方法中能感覺到是可以把小于10的區塊合并成一組。接著找11,再把小于11的相鄰元素合并成一組。接著找12,再把小于12的相鄰元素合并為一組。最終合并到右下角。這里合并的時候要考慮清楚合并的是元素的值,還是下標。因為最后判斷條件不同。在代碼swimInWaterV3中合并的是下標,所以最后判斷0和N*N-1在同一組,即可退出循環。
這種題目理解和代碼,這個等價關系也是令人驚嘆。hard類型的題目果然不同凡響。
代碼
827. Making A Large Island
思路:對于遇到的每個0,嘗試修改為1,用dfs數數面積;取最大的面積值.當grid中沒有0的時候,面積為n^2。
學習:將0周圍的1分組,可以連續在一起的1分為一組算一次面積。最后再將0周圍不同組的面積加起來。找到最大值就是面積。
代碼
總結
以上是生活随笔為你收集整理的Depth-first Search深度优先搜索专题4的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Shell脚本查询服务器硬件信息
- 下一篇: Hybrid和Tagged Untagg