一起刷演算法 # 二分查詢 # No.1
阿新 • • 發佈:2021-12-23
題目
153. 尋找旋轉排序陣列中的最小值 - 力扣(LeetCode) (leetcode-cn.com)
用時
39分鐘
結果
優化過程
第一次提交未通過,發現問題是因為對於 3 1 2這種,最小值剛好是mid的情況,無法正確尋找,因為它會跳過mid值。
這個時候我還沒意識到,這是因為這道題不是標準二分法的原因,而我使用了一般二分的一般形式。
class Solution { public int findMin(int[] nums) { int low = 0, hi = nums.length - 1; if(nums[low] < nums[hi])return nums[low]; if(nums.length == 2)return nums[0] > nums[1]? nums[1]:nums[0]; int mid = -1; while(low <= hi){ mid = low + (hi - low) / 2; System.out.println(mid); if(nums[mid] > nums[0]){ low = mid + 1; } else{ hi = mid - 1; } } return nums[mid]; } }
第二次提交,這個時候我加入了一個判斷條件
if(nums[mid] < nums[low] && nums[mid] < nums[hi])return nums[mid];
來處理這種mid是最小值的情況,但還是會有新的問題,這個時候我嘗試繼續加限制條件,但感覺不太對,這演算法看起來就太複雜了。於是開始思考為什麼不行。
class Solution { public int findMin(int[] nums) { int low = 0, hi = nums.length - 1; if(nums[low] < nums[hi])return nums[low]; if(nums.length == 2)return nums[0] > nums[1]? nums[1]:nums[0]; int mid = -1; int temp = -1; while(low <= hi){ mid = low + (hi - low) / 2; //System.out.print(mid); //System.out.print(low); //System.out.println(hi); if(nums[mid] < nums[low] && nums[mid] < nums[hi])return nums[mid]; if(nums[low] < nums[hi])return nums[low]; if(nums[mid] > nums[low]){ low = mid + 1; } else{ hi = mid - 1; } temp = mid; } return nums[mid]; } }
我發現,所有這些問題都是因為mid這個值在遍歷時被漏掉了!
簡單好理解的二分法! 要找這種序列的最小值,只需要思考,最小值到底在哪裡?最小值一定在無序部分中。 這些序列大概可以分為兩種情況: 1.前半部分有序:5678/912 2.後半部分有序:7812/345 我們發現,最小值一定在無序部分,那麼我們只需要不斷尋找無序部分就行了程式碼如下,這裡有一些問題: 1.如何尋找無序部分? 通過if(nums[mid]>=nums[low])這一句比較來尋找,即中間值和每次二分出來的部分的第一個值比較,這一點比較好理解. 還需要加上這一句if(nums[low]<=nums[hi])returnnums[low];表示剩下的序列全都是有序了,沒法再找無序部分,這個時候直接返回第一個值即是最小值。 2.為什麼hi=mid而不是mid-1 在一般二分中,我們可以寫mid-1和mid+1是因為我們有一句if(nums[mid]==target)break;**即每次我們都check到了mid位置的值,所以我們可以通過位置移動來排除這個值,但這個演算法裡是沒有這句break語句check到mid值的,所以不能-1 於是最終版為:
class Solution { public int findMin(int[] nums) { int low = 0, hi = nums.length - 1; if(nums[low] <= nums[hi])return nums[low]; int mid = -1; while(low <= hi){ mid = low + (hi - low) / 2; if(nums[low] <= nums[hi])return nums[low]; if(nums[mid] >= nums[low]){ low = mid + 1; } else{ hi = mid; //!!!!!!!!!!!這裡不能減去1 } } return nums[mid]; } }