1. 程式人生 > >Leetcode 34 Find First and Last Position of Element in Sorted Array 解題思路 (python)

Leetcode 34 Find First and Last Position of Element in Sorted Array 解題思路 (python)

本人程式設計小白,如果有寫的不對、或者能更完善的地方請個位批評指正!

這個是leetcode的第34題,這道題的tag是陣列,需要用到二分搜尋法來解答

 

34. Find First and Last Position of Element in Sorted Array

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6Output: [-1,-1]

 

思路:

這道題目的難點在於O(log n),看到了O(log n)想到的基本就是二分搜尋法,但怎麼實現呢?大致有以下兩種思路:

第一種: 先做一遍二分搜尋,如果不能找到

target的話返回(-1-1)如果能找到的話然後向左、向右搜尋進而找到最小和最大的target,返回index

這種解法的時間複雜度平均是O(log(n)),但當所有在陣列中的數字都是一樣的並且也都等於target的時候最差是O(n)

第二種: 做兩遍二分搜尋,如果不能找到target的話返回(-1-1)如果能找到的話第一遍返回最小的index,第二遍返回最大的index,這樣的話可以保證在最差的情況下時間複雜度是O(log(n))

很明顯第二種解法是優於第一種解法的。

那麼這兩種二分法的搜尋到底怎麼實現呢?具體方法見參考文獻【1】裡面的2.12.2

我們希望實現找到第一個與

target相等的元素和最後一個與target相等的元素

(1)找到第一個與target相等的元素,如果沒有的話返回-1

def search_first_target(self, nums, target):

        left,right = 0,len(nums)-1

        while (left <= right):

            mid = (left + right) >> 1

            if (nums[mid] >= target): # 注意1

                right = mid - 1

            else:

                left = mid + 1

        if nums[left] == target:

            return left   # 注意2

        else:

            return -1

(2)找到最後一個與target相等的元素,如果沒有的話返回-1

def search_last_target(self, nums, target):

        left,right = 0,len(nums)-1

        while (left <= right):

            mid = (left + right) >> 1

            if (nums[mid] > target): # 注意1

                right = mid - 1

            else:

                left = mid + 1

        if nums[right] == target:

            return right  # 注意2

        else:

            return -1

 

最後的實現只是需要把以上兩段程式碼合併到一起即可:

時間複雜度log(n)

Python 程式碼實現:

class Solution(object):

    def searchRange(self, nums, target):

        l,r = 0, len(nums)-1

        left, right = -1, -1

        while(l <= r):

            mid = (l+r)//2

            if (nums[mid] >= target):

                r = mid - 1

            else:

                l = mid + 1

        if nums[l] == target:

            print (nums[left],target)

            left = l

        else:

            return -1, -1

        l,r = 0, len(nums)-1

        while(l <= r):

            mid = (l+r)//2

            if (nums[mid] > target):

                r = mid - 1

            else:

                l = mid + 1

        if nums[r] == target:

            right = r

        return left, right

    if __name__ == "__main__":

        nums = [5,7,7,8,8,10]

        target = 3

        print(searchRange(0,nums,target))

 

參考文獻:

    1.分析了二分法的不同情況,寫的不錯https://www.cnblogs.com/luoxn28/p/5767571.html

     2. http://blog.csdn.net/int64ago/article/details/7425727