Leetcode1 全排列、全排列II、旋轉(zhuǎn)數(shù)組
主要總結(jié)做過的四道題目:
全排列,全排列II,尋找旋轉(zhuǎn)數(shù)組中的最小值,搜索旋轉(zhuǎn)數(shù)組

全排列這道題主要需要明確排列過程中的遞歸樹的結(jié)構(gòu),遞歸樹的結(jié)構(gòu)是這樣:

雖然這道題也可以通過交換數(shù)組下標對應的元素實現(xiàn)不同的組合,不過我覺得這種事方式不容易理解也不容易拓展。 這種遞歸樹的思想主要是嘗試每一種可能的元素分別放在字符串的第0到第n-1個下標,同時需要記錄哪些字符已經(jīng)被放置。這樣就可以寫出代碼:
在全排列II中需要找出不同的字符組合。因為假設存在相同的字符,有些組合會進行重復的嘗試。為了避免進行重復的嘗試,需要觀察遞歸樹

如果C和B相同,則不需要走C的分支。為了讓這種判斷更加自然和方便,我們首先需要將數(shù)組排序,這樣相同的字符會接近,如果已經(jīng)試探過,則直接跳過。 這樣在全排列I的基礎上,我們需要加一條額外判斷:
其實這個條件中!visited[j-1]是最值得玩味的。在我們遞歸結(jié)構(gòu)中,當訪問完成的時候會恢復現(xiàn)場,visited,perms都會恢復狀態(tài),當visited[j-1] = false時,說明前一個字符的后續(xù)組合已經(jīng)被記錄了,就像上圖中的AB節(jié)點和其子樹。

尋找旋轉(zhuǎn)數(shù)組的最小值:

當數(shù)組經(jīng)過了若干次旋轉(zhuǎn),可能的情況有三種:
上圖中(1)此時,通過左右下標構(gòu)成的子數(shù)組是遞增序列,最小值在【中】的左邊,收縮右邊
上圖中(2)此時通過“斷崖”分割的左邊整體會高于斷崖的右邊,最小值在中間的左邊,收縮右邊
上圖中(3)和上面類似,最小值在【中】的右邊,收縮左邊。
從上面三種情況看來,情況1、2都可以通過對比【中】和【右】進行界定,兩者可以合并。
下面具體來分析為什么這個代碼可以這么寫:
? 因為使用mid = left + (rigth - left) / 2,會使得mid的值更接近left 。
當數(shù)組長度等于1時,left = mid = right,left和right都保存了數(shù)組的最小值
當數(shù)組長度等于2時,left = mid = right-1 ,若nums[mid] < nums[right] right = mid=left,退出循環(huán);其他情況時,left = mid + 1 = right,退出循環(huán),left和right都保存了最小值的下標。
對于搜索旋轉(zhuǎn)數(shù)組中的最小值,直接找到數(shù)組的最小值下標,劃分成兩個數(shù)組就可以解決了。