1. 程式人生 > 其它 >獻芹奏曝-Python面試題-演算法-動態規劃篇 獻芹奏曝-Python面試題 

獻芹奏曝-Python面試題-演算法-動態規劃篇 獻芹奏曝-Python面試題 

     上一篇:獻芹奏曝-Python面試題 

      開篇的話:本文目的是收集和歸納力扣上的演算法題,希望用python語言,竭我所能做到思路最清奇、程式碼最簡潔、方法最廣泛、效能最高效,瞭解常見題目,找到最利於記憶的答案,更加從容的應對面試。希望廣思集益,共同進步。 

動態規劃篇 

  1. 70. 爬樓梯(難度係數✯)

    class Solution:
        def climbStairs(self, n: int) -> int:
            if n == 1:
                return 1
            elif n == 2:
                
    return 2 else: return self.climbStairs(n - 1) + self.climbStairs(n - 2)
    方法一

    執行結果:1:超時

    知識點/技巧: 遞迴呼叫,會有大量重複計算

    class Solution:
        dict_result = {}
    
        def climbStairs(self, n: int) -> int:
            if self.dict_result.get(n):
                return self.dict_result.get(n)
            
    if n == 1: self.dict_result[n] = 1 return 1 elif n == 2: self.dict_result[n] = 2 return 2 else: self.dict_result[n] = self.climbStairs(n - 1) + self.climbStairs(n - 2) return self.dict_result[n]
    方法二

    執行結果:1:耗時超過54%。2:記憶體超過79% 

    知識點/技巧:通過字典,將計算過的值儲存,減少重複計算

    class Solution:
        def climbStairs(self, n: int) -> int:
            if n == 1:
                return 1
            a = [1] * (n + 1)
            a[1] = 1
            a[2] = 2
            for i in range(3, n+1):
                a[i] = a[i - 1] + a[i - 2]
            return a[n]
    方法三

    執行結果:1:耗時超過79%。2:記憶體超過89% 

    知識點/技巧:通過陣列,求和的速度更快,根據索引取值,比字典查詢更快

    class Solution:
        def climbStairs(self, n: int) -> int:
            if n == 1:
                return 1
            first = 1
            second = 2
            for i in range(3, n + 1):
                first, second = second, first + second
            return second
    方法四

    執行結果:1:耗時超過79%。2:記憶體超過75% 

    知識點/技巧:通過數字滾動的方式,但是疑惑的是,並沒發現記憶體空間提升多少
    當然還有一些其他方法,矩陣法、通項公式法,這裡不一一介紹

  2. 53. 最大子陣列和(難度係數✯)

    class Solution:
        def maxSubArray(self, nums: List[int]) -> int:
            # 構造和目標陣列一樣長度的陣列
            r = nums.copy()
            for i in range(1, len(nums)):
                if r[i - 1] > 0:
                    r[i] += r[i - 1]
            return max(r)
    方法一

    執行結果:1:耗時超過78%。2:記憶體超過15% 。

    知識點/技巧: 

    為了便於理解記憶:可以想象成一個賭徒賭博,什麼時候,手中籌碼最多,
    我們記錄每一把賭牌後的手中籌碼數,當然有一點不同的是,
    如果上一步贏了,或者還有剩餘,我們財富積累,
    如果上一步錢輸光了,往事隨風,另起爐灶,重新開始,從當前記錄
    class Solution:
        def maxSubArray(self, nums: List[int]) -> int:
            if len(nums) == 1:
                return nums[0]
            top_one = nums[0]
            for i in range(1, len(nums)):
                if nums[i - 1] > 0:
                    nums[i] += nums[i - 1]
                if nums[i] > top_one:
                    top_one = nums[i]
            return top_one
    方法二

    執行結果:1:耗時超過70%。2:記憶體超過36% 

    知識點/技巧:通過數字滾動的方式,節省記憶體

  3. 416. 分割等和子集(難度係數✯)

    """
    1:要想使得分割成後的兩個子集和相等,那麼:和必須為偶數
    2:我們馬上可以轉換成0-1揹包問題:即每個物品可以出現0次或1次
    3:                     0   1   2   3   4   5   6   7   8   9   10  11
    第一個物品放或者不放      √   √
    第二個物品放或者不放      √   √               √   √                       如果第二個物品5沒放,那就是原來的值,如果5放了,那就是在原來的基礎上向後移動5個單位
    第三個物品放或者不放      √   √               √   √                √   √
    但是需要注意的是放與不放這個動作一氣呵成,
    """
    from typing import List
    
    
    class Solution:
        def canPartition(self, nums: List[int]) -> bool:
            s = sum(nums)
            if s % 2:
                # 1:要想使得分割成後的兩個子集和相等,那麼:和必須為偶數
                return False
            target = s // 2
            a = [False] * (target + 1)
            a[0] = True
            for index_n, n in enumerate(nums):
                if n > target:
                    # 2:如果遍歷的元素比目標值大,說明沒有找到結果,返回False
                    return False
                change_index = []
                for index, item in enumerate(a):
                    if item:
                        if index + n > target:
                            for c_index in change_index:
                                a[c_index] = True
                            break
                        if index + n == target:
                            return True
                        else:
                            change_index.append(index + n)
                else:
                    # 為什麼只有在退出的時候才統一賦值,[1,2,5] 此時會出錯
                    for c_index in change_index:
                        a[c_index] = True
            return False
    方法一

    執行結果:1:耗時超過95%。2:記憶體超過83%

    知識點/技巧: 轉換成01揹包問題,詳情看程式碼中註釋

    class Solution:
        def canPartition(self, nums: List[int]) -> bool:
            s = sum(nums)
            if s % 2:
                # 1:要想使得分割成後的兩個子集和相等,那麼:和必須為偶數
                return False
            target = s // 2
            a = [False] * (target + 1)
            a[0] = True
            for index_n, n in enumerate(nums):
                if n > target:
                    # 2:如果遍歷的元素比目標值大,說明沒有找到結果,返回False
                    return False
                for i in reversed(range(0, target - n + 1)):
                    if a[i]:
                        if i + n == target:
                            return True
                        a[i + n] = True
            return False
    方法二

    執行結果:1:耗時超過96%。2:記憶體超過99%

    知識點/技巧: 倒敘遍歷,是列表變化(長度、內容)的剋星

    class Solution:
        def canPartition(self, nums: List[int]) -> bool:
            s = sum(nums)
            if s % 2:
                # 1:要想使得分割成後的兩個子集和相等,那麼:和必須為偶數
                return False
            target = s // 2
            a = [False] * (target + 1)
            dir_list = {0: True}
            for n in nums:
                if n > target:
                    # 2:如果遍歷的元素比目標值大,說明沒有找到結果,返回False
                    return False
                list_keys=[]
                for key in reversed(list(dir_list.keys())):
                    if dir_list.get(target - n):
                        return True
                    list_keys.append(key + n)
                else:
                    for l_key in list_keys:
                        dir_list[l_key] = True
            return False
    方法三

    執行結果:1:耗時超過96%。2:記憶體超過43%

    知識點/技巧:利用雜湊表實現,實現快速查詢

  4. 217. 存在重複元素(難度係數✯)

    方法一

    執行結果:1:耗時超過40%。2:記憶體超過33%。3:程式碼簡潔

    知識點/技巧: 利用set去重,比較長度

    方法二

    執行結果:1:耗時超過76%。2:記憶體超過30%。

    知識點/技巧: 利用字典記錄字母出現次數

  5.