852. Peak Index in a Mountain Array

Description

Let’s call an array arr a mountain if the following properties hold:
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]
Given an integer array arr that is guaranteed to be a mountain, return any i such that arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1].

Thoughts

We can traverse the whole list and find the first position i that has arr[i + 1] > arr[i] since there is not dup in the problem. The time complexity is O(n)

We find some regularity in the array. It’s increasing and then decreasing. We can use binary search to see if the peak is in the first half or the last half. This will reduce the time complexity to O(logn)


Exceptions

  • No special cases if we use bruteforce to traverse the list.
  • It’s important that there’s no duplicate numbers in the array. Otherwise the binary search method will not work. Because for the mid with nums[mid + 1] == nums[mid] we cannot identify which part it should be.
  • To avoid any index out of range or infinite loop, we only consider the binary part when the length of sliced array is larger than 2. For any array that has only 1 or 2 elements, we just compare the elements and return the large one.

Python Code

Brute-force

    def peakIndexInMountainArray(self, arr: List[int]) -> int:       
        for i in range(len(arr) - 1):
            if arr[i + 1] < arr[i]:
                return i

While-loop Binary Search

    def peakIndexInMountainArray(self, arr: List[int]) -> int:
        start, end = 0, len(arr) - 1
        '''
        This is to avoid index out of range or infinite loop
        '''
        while start < end - 1:
            mid = (start + end) // 2
            if arr[mid + 1] > arr[mid]:
                start = mid
            if arr[mid + 1] < arr[mid]:
                end = mid
        '''
        We have 1 or 2 elements after the while loop.
        Need to check them and return the large one.
        '''
        if arr[start] >= arr[end]:
            return start
        return end

Recursive Binary Search

    def peakIndexInMountainArray(self, arr: List[int]) -> int:
        return self.binarysearch(arr, 0, len(arr) - 1)
        
    def binarysearch(self, arr, start, end):
        '''
        This is the same as start < end - 1 in above while-loop.
        We only do binary search to the array which has at least 
        3 elements to avoid index out of range or infinite loop.
        In recursive method, we treat them as special cases and check it at the begining.
        '''
        if start >= end - 1:
            if arr[start] >= arr[end]:
                return start 
            return end
        
        mid = (start + end) // 2
        if arr[mid + 1] > arr[mid]:
            return self.binarysearch(arr, mid, end)
        if arr[mid + 1] < arr[mid]:
            return self.binarysearch(arr, start, mid)

Summary

We can think of binary search if we see any array related problems which has the up or down trend. We can try binary search as long as we can find rules to check if the result is in the left side and right side.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值