1. 程式人生 > >LeetCode 45 Hard 跳躍遊戲2 Python

LeetCode 45 Hard 跳躍遊戲2 Python

方法一:

    演算法:貪心

    思路

        首先要注意到:

            題設是一定可以從頭部節點到達尾部節點,和55題類似,如果一個節點可以從i到達j,那麼一定可以到達i和j中間

        的任何一個節點i,i+1.i+2,...,j-1,j。同理,這裡的題設已經使得陣列從0開始一定可以一步一步從0,1,2,3...last

        抵達last節點,也就是從0開始一步一步就遍歷陣列一定是正確的遍歷方式,關鍵在於何時跳躍,跳躍幾次

        何時跳躍?

            在逐個遍歷陣列的過程中,到達某一位置時,發現從當前位置起跳無法到達更遠的位置,由於從0開始一定能到達最

        後一個位置,那麼就意味著在當前位置之前,必然有1次跳躍,且跳躍到更遠的位置,事實上在該位置之前有多個可以跳

        越到更遠位置的地方,那麼應該選擇跳到哪裡?(這時候起跳位置就不重要了,重要的是能跳到哪裡去,因為這裡要記錄的

        是跳躍的次數,並不是跳躍的位置,當然瞭如果要求跳躍的序列,也可以記錄下來,問題不大)。答:應該跳值最遠的那個

        地方,貪心的思想

        SO:

            1. 設定jump_before_end 記錄最小跳躍次數,注意這裡初始值為1,它代表的是到達last前必要的跳躍次數

                經過某個位置後才發現該位置不能跳更遠的位置才記錄的過去應該有一次跳躍,像一根繩子分3段要切2刀

            2. 設定pre_max_reach記錄已遍歷位置中最遠可達位置

               curr_max_reach 為從頭開始遍歷的過程中整個過程裡最遠可達位置的變化情況,i就是和這個比較

            3. i 遍歷所有位置,用pre_max_reach更新已經遍歷過的這一段中最遠可達位置,curr_max_reach跟蹤

               整個遍歷過程中的最遠可達位置,當前位置i>當前整個過程的curr_max_reach時則應該jump+1表明

               在此之前必然有一次跳躍,並且更新curr_max_reach

    複雜度分析

        時間:ON,遍歷一次陣列

        空間:O1,常數級

def jump_0(self, nums):

    if len(nums) < 2:

        return 0

    jump_befor_end = 1

    pre_max_reach = nums[0]

    curr_max_reach = nums[0]

    for i in range(1, len(nums)):

        if i > curr_max_reach:

            jump_befor_end += 1

            curr_max_reach = pre_max_reach

        pre_max_reach = max(pre_max_reach, i + nums[i])

    return jump_befor_end

 

  方法二:

    演算法:與jump_1 思路類似,貪心

    思路

            將遍歷過程(跳躍過程,因為0到last可達,故可達0,1,2..last任何一個位置,所以可以遍歷)看做是一段一段的

        每一段都跳到最遠可達的那個位置

 

            記錄當前遍歷的情況,記錄當前可達最遠距離curr_farthest,在遍歷陣列的過程中更新curr_farthest,

        如果已經抵達當前段的最遠位置,再往後走就要跳了,所以counter += 1,更新下一段最遠可達位置為之前記錄的

        最遠可達位置,類似jump_0中的curr_max_reach = pre_max_reach

 

            這裡的range只到len(nums)-1是因為,程式只要在到達end時就會+1,由於必然會跳到最後一個節點,那麼如果

        條件是 range(len(nums)),則會抵達了最後一個節點,出發i == curr_end 的判斷條件,由此一來程式會認為

        最後一個節點處又要開始起跳,counter += 1,會多加一次不必要的跳躍,所以遍歷到last-1位置即可

 

    與jump_0對比

            二者其實非常相似,都是記錄當前的遍歷情況和跳躍情況

            但是jump_0關注的是【超過】跳躍點之後,即繼續往下無法到達更遠的位置,那麼在之前會有一次跳躍,因此counter += 1

            jump_1關注的是當前的遍歷和跳躍情況,如果我遍歷到了【本段】的最後一個位置,那麼就應該跳躍到下一個更遠的位置去

 

            所以要注意二者counter += 1 的時刻,條件,背景是與意義是不相同的

 

    複雜度分析

        時間:ON,遍歷一次陣列

        空間:O1,常數級

def jump_1(self,nums):

    counter = 0

    curr_end = 0

    curr_farthest = 0

    for i in range(len(nums)-1):

        curr_farthest = max(curr_farthest, i + nums[i])

        if i == curr_end:

            counter += 1

            curr_end = curr_farthest

    return counter
"""

從Details中看的一個submit,不是很直觀,也沒細看

if not nums or len(nums) <= 1:

            return 0

        slow, fast = 0, 0

        step = 0

        last = len(nums) - 1

        while slow <= fast:

            step += 1

            old_fast = fast

            for i in range(slow, fast+1):

                fast = max(fast, i + nums[i])

                if fast >= last:

                    return step

            slow = old_fast + 1

        return 0

"""