1. 程式人生 > 其它 >162. 尋找峰值(python3)

162. 尋找峰值(python3)

技術標籤:leetcode mediumbinary searchleetcode

題目:https://leetcode-cn.com/problems/find-peak-element/

峰值元素是指其值大於左右相鄰值的元素。

給定一個輸入陣列nums,其中 nums[i] ≠ nums[i+1],找到峰值元素並返回其索引。

陣列可能包含多個峰值,在這種情況下,返回任何一個峰值所在位置即可。

你可以假設nums[-1] = nums[n] = -∞。

示例 1:

輸入: nums = [1,2,3,1]
輸出: 2
解釋: 3 是峰值元素,你的函式應該返回其索引 2。
示例2:

輸入: nums = [1,2,1,3,5,6,4]

輸出: 1 或 5
解釋: 你的函式可以返回索引 1,其峰值元素為 2;
或者返回索引 5, 其峰值元素為 6。


說明:

你的解法應該是O(logN)時間複雜度的。

解題思路:

此題雖然不是升序數列,但可以藉助二分的方法進行查詢。
值得注意的是nums[-1] = nums[n] = -∞,即數列左側第一個值所在子序列是降序或右側第一個值所在子序列是升序就滿足峰值定義
比較mid與mid+1位上的數,如果nums[mid] < nums[mid+1],證明峰值存在於mid的右邊,最壞程度是右側全部是升序,則右側最後一個值是峰值。
也可以比較mid與mid-1位上的數,如果nums[mid] < nums[mid-1],證明峰值存在於mid的左邊,最壞程度是左邊全是降序,則左側第一個值是峰值。使用左側比較需注意:因為mid是start + (end - start) // 2,在陣列排除的僅剩兩個元素時,mid=start,

此時mid-1會越界,需對這種情況進行單獨判斷。

程式碼1:

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        start = 0
        end = len(nums) - 1

        while(start <= end):
            mid = start + (end - start) // 2

            if(mid+1 > end):
                return mid
            if(nums[mid] < nums[mid+1]):
                start = mid + 1
            else:
                end = mid
            
        return mid

程式碼2:



class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        start = 0
        end = len(nums) - 1

        while(start <= end):
            mid = start + (end - start) // 2

            if(end - start == 0):
                return mid
            if(end - start == 1):
                if(nums[end] > nums[start]):
                    return end
                else:
                    return start

            if(nums[mid] < nums[mid-1]):
                end = mid - 1
            else:
                start = mid
            
        return mid
    

測試用例:

if __name__ == "__main__":
    nums = [1,2,1,3,5,6,4]
    res = Solution().findPeakElement(nums)
    print(res)