每天一道leetcode-33

  • 2019 年 10 月 4 日
  • 筆記

前言

目前準備每天刷一道題leetcode的題目,以此來激勵那些零基礎入門的人,千萬不要被什麼科班和非科班的說法嚇倒了,電腦這個行業只要你肯努力,沒有什麼逾越不了的鴻溝。

只要你肯努力,一份努力,一份汗水,在程式設計師這個職業,你的每一份付出都會得到對應的那一份彙報,尊重學習規律,循序漸進,別想著一口吃個胖子,羅馬也不是一天建成的,有朝一日,你終會變成你想成為的人。

題目目前可能需要一定的演算法與數據結構基礎才能看懂,後序會寫一下零基礎也能看懂的入門知識,然後就可以看懂我編寫的題目了~

案例

題目

leetcode33 在旋轉數組中查找一個數n

tag(標籤):二分查找

原題鏈接:

https://leetcode.com/problems/search-in-rotated-sorted-array/

題目詳述

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

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

搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。

你可以假設數組中不存在重複的元素。

你的演算法時間複雜度必須是 O(log n) 級別。

示例 1:

輸入: nums = [4,5,6,7,0,1,2], target = 0輸出: 4

示例 2:

輸入: nums = [4,5,6,7,0,1,2], target = 3輸出: -1

題解

先上程式碼,準備結合著程式碼進行講解。

class Solution {      public int search(int[] nums, int target) {          if(nums.length == 0)              return -1;          int left = 0;          int right = nums.length - 1;          while(left <= right)          {              int mid = left + (right-left)/2;              if(nums[mid] == target)                  return mid;              else if(nums[left] == target)                  return left;              else if(nums[right] == target)                  return right;              else{                  if(target > nums[mid])                  {//1                      if(nums[mid] > nums[0])                      {//2                          left = mid + 1;                      }else                      {                          if(target > nums[0])//3                              right = mid - 1;                          else                              left= mid + 1;                      }                  }                  else{                      if(nums[mid] > nums[0])                      {//4                          if(target < nums[0])//5                              left = mid + 1;                          else                              right = mid - 1;                      }                      else{                          right = mid - 1;                      }                  }              }          }          return -1;      }  }  

對於這種題目,數組,有序這兩個字眼結合起來,就是要第一時間考慮到二分查找。不懂什麼是二分查找的參考我的這篇文章。RNG輸了,但我們不能輸

假設有這樣一個旋轉數組[4,5,6,7,8,0,1,2,3],我用圖形化的方式表示為下圖,方便大家理解,前一段代表4,5,6,7,8,後一段代表0,1,2,3。

下圖只是一種情況,後序有多種情況,後序不再是這個數組

思路:由於無法確定target,nums[mid]誰大誰小,以及target和nums[mid]到底在前半段,還是在後一段,不同的情況下,對於令left = mid+1還是right = mid-1是不一樣的情況,所以這裡分情況進行討論,把所有的情況討論一遍,然後就知道,到底是變化left還是變化right,進而去縮小這個區間,找到我們要找到的數。

target>nums[mid]

情況1

在第18行上,target大於nums[mid]時,緊接著19行,繼續討論nums[mid]與nums[0]的情況,當nums[mid]大於nums[0],也就是說明了nums[mid]一定在前半段,而target是大於nums[mid]的,target必然在前半段,所以這個時候肯定就是要把left=mid+1 才可以去逼近這個target.

情況2

當target大於nums[mid]時候,19行判斷後發現nums[mid]小於nums[0],所以這時候,nums[mid]必然在後半段。而targe是大於nums[mid],但target大於nums[mid]的話有兩種情況,一種是target在前半段,一種是在後半段,如下兩圖所示

上圖就是target在前半段的情況,也就是程式碼24行的判斷target>nums[0],這個時候,看圖,得知應該是right=mid-1,向target逼近!

上圖就是target在後半段的情況,在程式碼24行判斷不成立,看圖得知應該left=mid+1,向target逼近。

target<nums[mid]

情況3

在程式碼17行判斷返回false,也就是target<nums[mid]這個大前提下。進入到30行程式碼。

進入到31行程式碼,當nums[mid] > nums[0],mid在前半段,而target是小於nums[mid],target不知道是在前半段,還是在後半段,所以得分情況討論

target在後半段 target<nums[0]

看上面圖,明顯應該是left = mid + 1;向target逼近;

target在前半段target>nums[0]

上圖顯示,明顯應該是right=mid-1;

情況4

當程式碼31判斷為假,那麼進入38行。也就是nums[mid]在後半段。

而大前提是target小於nums[mid],所以target必然在後半段。

如上圖所示,所以right=mid-1,去逼近target。

結束語

以上就是我的思路,把所有的情況自己心裏面想清楚,我感覺是用筆畫圖好一些,更加的清晰明了,自己把所有的情況知道以後,那麼寫起來就下筆如有神了。

END