一魚多吃 用二分搜尋法 找目標值 Find in Mountain Array_Leetcode #1095

更新於 發佈於 閱讀時間約 6 分鐘

這題的題目在這裡:

題目敘述

題目會給我們一個山形的輸入陣列,和目標值target,要求我們找出目標值所在的陣列索引。如果出現兩次,返回比較小的那一個,也就是比較靠左的那個索引值。

山形的意思就是說,從最左側到山頂最大值都是遞增,從山頂最大值到右側都是遞減。

You may recall that an array arr is a mountain array if and only if:

  • arr.length >= 3
  • There exists some i with 0 < i < arr.length - 1 such that:
    • arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
    • arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
raw-image

測試範例

Example 1:

Input: array = [1,2,3,4,5,3,1], target = 3
Output: 2
Explanation: 3 exists in the array, at index=2 and index=5. Return the minimum index, which is 2.

Example 2:

Input: array = [0,1,2,4,2,1], target = 3
Output: -1
Explanation: 3 does not exist in the array, so we return -1.



約束條件

Constraints:

  • 3 <= mountain_arr.length() <= 104
  • 0 <= target <= 109
  • 0 <= mountain_arr.get(index) <= 109

演算法

這題也是屬於二分搜尋法的應用題。
因為題目已經說是山形陣列,我們可以先用二分搜尋法找出最大值,也就是山頂。如同前面這題我們學過的技巧,來找山形陣列的絕對最大值。

找到山頂之後,整個陣列可以分成兩塊,左邊這塊剛好都是遞增的分布,右邊這塊剛好都是遞減的分布。不論是在左邊找,還是在右邊找,都是在已經排序好的子陣列尋找目標值,恰好符合二分搜尋法的應用場景。

接著先找左邊這塊,假如左邊這塊找不到再找右邊這塊;如果,最後還是找不到,就返回-1,代表找不到目標值。


程式碼

class Solution:
 
 def findPeak(self, mountain_arr) -> int:
  
  left, right = 0, mountain_arr.length()-1
  
  while left < right :
   
   probe = left + ( right - left ) // 2
   
   if mountain_arr.get(probe) > mountain_arr.get(probe+1):
    right = probe
   else:
    left = probe + 1
    
  return right
 
 

 def findTarget(self, mountain_arr, peak_index, target) -> int:
  
  # Phase_#1: Find Target in uphill
  left, right = 0, peak_index
  
  while left <= right:
   
   probe = left + ( right - left ) // 2
   
   probe_value = mountain_arr.get( probe )
   
   if probe_value == target:
    return probe
   
   elif probe_value < target:
    left = probe+1
   
   else:
    right = probe-1
  
  
  # Phase_#2: Find Target in downhill
  left, right = peak_index, ( mountain_arr.length()-1 )
  
  while left <= right:
   
   probe = left + ( right - left ) // 2
   
   probe_value = mountain_arr.get( probe )
   
   if probe_value == target:
    return probe
   
   elif probe_value < target:
    right = probe-1
   
   else:
    left = probe+1
    
  return -1
   
 

 def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
  
  # Find mountain peak
  peak_index = self.findPeak(mountain_arr)
  
  # Find target in up-hill,then down-hill, or target does not exist in montain
  index_of_target = self.findTarget( mountain_arr, peak_index, target)
  
  return index_of_target



複雜度分析

時間複雜度: O( log n)
都是用二分搜尋法來找最大值(山頂)和目標值(target)。

T(n) = T(n/2) + O(1),

T(n) = O( log n )

空間複雜度: O(1)

所用到的都是固定的臨時變數,所占用的記憶體空間為常數級別O(1)


關鍵知識點

在已經排序好的陣列尋找目標值,聯想到二分搜尋法,這是標準的二分搜尋法的應用場景。

建議回頭複習高度關聯的題目:

Binary search, 找絕對最大值, 找相對最大值


Reference:

[1] Python O( log n ) sol. based on variant binary-search, run-time 88%+ - Find in Mountain Array - LeetCode

avatar-img
90會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
題目給定一個已排序的輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目會給定一個2D 二維的矩陣,矩陣內的元素值代表對應的高度,要求我們找出相對最高點,也就是(大樓)高度大於N4 東、南、西、北 四個鄰居的索引值。 題目保證矩陣內相鄰的元素值都不相同,也又是相鄰的兩兩相比較,一定有一個比較高,有一個比較矮。
題目會給定一個陣列,陣列裡面的元素分布就像一座山峰。 最大值的左邊都是上坡段,最大值的右邊都是下坡段。 要求我們找出陣列裡面的絕對極大值(absolute max value)所在的陣列索引
題目會給定一個陣列,裡面有大有小,可以把數字的大小類比成高度 要求我們找出陣列裡面的相對極大值(relative max value)所在的陣列索引 也就是說當下這個元素,大於左邊鄰居的元素值,也大於右邊鄰居的元素值
這題的題目在這裡 題目會給定一個輸入整數x, 要求我們返回x的正整數平方根(取無條件捨去小數部分的正整數值)
題目會給我們一個排序好的矩陣matrix ,和一個目標值 target 要求我們在矩陣中尋找target,如果存在,返回True。 如果target 不存在,返回False 題目要求必須在O( log (m*n) )對數時間內完成 。
題目給定一個已排序的輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目會給定一個2D 二維的矩陣,矩陣內的元素值代表對應的高度,要求我們找出相對最高點,也就是(大樓)高度大於N4 東、南、西、北 四個鄰居的索引值。 題目保證矩陣內相鄰的元素值都不相同,也又是相鄰的兩兩相比較,一定有一個比較高,有一個比較矮。
題目會給定一個陣列,陣列裡面的元素分布就像一座山峰。 最大值的左邊都是上坡段,最大值的右邊都是下坡段。 要求我們找出陣列裡面的絕對極大值(absolute max value)所在的陣列索引
題目會給定一個陣列,裡面有大有小,可以把數字的大小類比成高度 要求我們找出陣列裡面的相對極大值(relative max value)所在的陣列索引 也就是說當下這個元素,大於左邊鄰居的元素值,也大於右邊鄰居的元素值
這題的題目在這裡 題目會給定一個輸入整數x, 要求我們返回x的正整數平方根(取無條件捨去小數部分的正整數值)
題目會給我們一個排序好的矩陣matrix ,和一個目標值 target 要求我們在矩陣中尋找target,如果存在,返回True。 如果target 不存在,返回False 題目要求必須在O( log (m*n) )對數時間內完成 。
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
強者都一日單攻雪山主峰順道撿個雪山東峰,小弟我是弱雞,只能單攻雪山東峰。 從標高2140公尺的大水池登山口,到標高3201公尺的雪山東峰,總共5K的路程,爬升1061公尺。
※ 常用arry型態的方法: 長度: length 查詢第N個元素: [] 查詢元素在第N個: indexOf( ) 判斷是否為array: isArray() 新增和刪除: push():新增後面的數值 unshift():新增前面的數值 pop():刪除後面的數值 sh
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
魔鬼藏在二分搜尋裡!輸出值代表的意含、題意產生的邊界條件,寫完模板才是挑戰的開始 Orz
(略),array 是用來將陣列的值進行累加,我們來看看怎麼怎麼達成吧: Given an integer array nums, a reducer function fn, and an initial value init, return the final result obtained
Thumbnail
題目 : 28. Find the Index of the First Occurrence in a String
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
強者都一日單攻雪山主峰順道撿個雪山東峰,小弟我是弱雞,只能單攻雪山東峰。 從標高2140公尺的大水池登山口,到標高3201公尺的雪山東峰,總共5K的路程,爬升1061公尺。
※ 常用arry型態的方法: 長度: length 查詢第N個元素: [] 查詢元素在第N個: indexOf( ) 判斷是否為array: isArray() 新增和刪除: push():新增後面的數值 unshift():新增前面的數值 pop():刪除後面的數值 sh
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
魔鬼藏在二分搜尋裡!輸出值代表的意含、題意產生的邊界條件,寫完模板才是挑戰的開始 Orz
(略),array 是用來將陣列的值進行累加,我們來看看怎麼怎麼達成吧: Given an integer array nums, a reducer function fn, and an initial value init, return the final result obtained
Thumbnail
題目 : 28. Find the Index of the First Occurrence in a String