天天看點

154. 尋找旋轉排序數組中的最小值 II hardLeetcode筆記目錄一、題目描述二、解題過程三、總結

Leetcode筆記目錄

154. 尋找旋轉排序數組中的最小值 II hard

  • Leetcode筆記目錄
  • 一、題目描述
  • 二、解題過程
    • 1.思想
    • 2.代碼
  • 三、總結

一、題目描述

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。

( 例如,數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。

請找出其中最小的元素。

注意數組中可能存在重複的元素,且數組不一定進行了旋轉。

示例1:

  • 輸入: [1,3,5]

    輸出: 1

示例2:

  • 輸入: [2,2,2,0,1]

    輸出: 0

二、解題過程

1.思想

與Leetcode33,81同是旋轉數組題目,本題充分利用了旋轉數組的特性(在斷點處左右分為兩個有序序列,且左邊的值一定大于右邊),本題即為用二分法尋找旋轉數組的斷點(如果旋轉了的話):

  • 本題的特性适合使用左閉右開,因為不是尋找值為target的項,而是找到最後得到left=right的單元素數組,邏輯為不斷比較端點和mid的值縮小斷點的區間直到縮到單元素數組,使用左右端點皆可,但右端點比較合适;
  • 以右端點為例比較:若nums[mid]>nums[right],則斷點定在[mid+1,right],否則的話,斷點定在[left,mid],若相等,則right-1。
  • 若以左端點比較,則需要多兩個判斷,即左端點比較無法處理無旋轉數組和left剛好是斷點的情況(此時left會+1)。

2.代碼

左端點版本:

int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        if (nums[left] < nums[right]) {  //無旋轉數組單獨處理
            return nums[left];
        }
        while (left < right) {
            int mid = left + (right-left) / 2;
            if (left > 0 && nums[left] < nums[left - 1]) {   //left剛好是斷點單獨處理
                return nums[left];
            }
            if (nums[left]<nums[mid]) {
                left = mid + 1;
            } else if (nums[left]>nums[mid]) {
                right = mid;
            } else {
                left++;
            }
        }
        return nums[left];
    }
           

右端點版本:

int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        while (left < right) {
            int mid = left + (right-left) / 2;
            if (nums[right]<nums[mid]) {
                left = mid + 1;
            } else if (nums[right]>nums[mid]) {
                right = mid;
            } else {
                right--;
            }
        }
        return nums[left];
    }
           

三、總結

不是有序數組不能套模闆,邊界需要很小心的讨論。

繼續閱讀