兩個常規動態規劃算法題,兩個邪門的解

下面是兩道很是經典的動態規劃算法題,來自力扣,解法也是老生常談。可是在各自速度排名第一的兩個解法很是不一樣尋常,開個坑,之後分析。python

LeetCode 322 零錢兌換

給定不一樣面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算能夠湊成總金額所需的最少的硬幣個數。若是沒有任何一種硬幣組合能組成總金額,返回 -1。

示例 1:算法

輸入: coins = [1, 2, 5], amount = 11
輸出: 3
解釋: 11 = 5 + 5 + 1
示例 2:網絡

輸入: coins = [2], amount = 3
輸出: -1
說明:
你能夠認爲每種硬幣的數量是無限的。app

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/probl...
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。函數

class Solution(object):
    def coinChange(self, coins, amount):
        def dfs(idx, target, cnt):
            if idx == len(coins):
                return
            if (target + coins[idx] - 1) / coins[idx] + cnt >= self.ans:
                return
            if target % coins[idx] == 0:
                self.ans = min(self.ans, cnt + target / coins[idx])
                return 
            for j in range(target / coins[idx], -1, -1):  
                dfs(idx + 1, target - coins[idx] * j, cnt + j)

        self.ans = float('inf')
        coins = list(set(coins)) 
        coins.sort(reverse=True)
        dfs(0, amount, 0)
        return -1 if self.ans == float('inf') else self.ans

LeetCode 72 編輯距離

給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少操做數 。

你能夠對一個單詞進行以下三種操做:code

插入一個字符
刪除一個字符
替換一個字符
示例 1:leetcode

輸入: word1 = "horse", word2 = "ros"
輸出: 3
解釋:
horse -> rorse (將 'h' 替換爲 'r')
rorse -> rose (刪除 'r')
rose -> ros (刪除 'e')
示例 2:get

輸入: word1 = "intention", word2 = "execution"
輸出: 5
解釋:
intention -> inention (刪除 't')
inention -> enention (將 'i' 替換爲 'e')
enention -> exention (將 'n' 替換爲 'x')
exention -> exection (將 'n' 替換爲 'c')
exection -> execution (插入 'u')it

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/probl...
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。io

class Solution:
    def minDistance(self, word1, word2):
        if not word1 or not word2:
            return max(len(word1),len(word2))
        stack1=[(0,0,0)]
        stack2=[(len(word1),len(word2),0)]
        mem1={}
        mem2={}
        while True:
            newstack1=[]
            while stack1:
                i,j,lv=stack1.pop()
                if (i,j) in mem2:
                    return lv+mem2[(i,j)]
                if (i,j) in mem1:
                    continue
                else:
                    mem1[(i,j)]=lv
                if i<len(word1) and j<len(word2):
                    if word1[i]==word2[j]:
                        stack1.append((i+1,j+1,lv))
                        continue
                    else:
                        #rep
                        newstack1.append((i+1,j+1,lv+1))
                #add
                if j<len(word2):
                    newstack1.append((i,j+1,lv+1))
                #del
                if i<len(word1):
                    newstack1.append((i+1,j,lv+1))
            stack1=newstack1
            
            newstack2=[]
            while stack2:
                i,j,lv=stack2.pop()
                if (i,j) in mem1:
                    return lv+mem1[(i,j)]
                if (i,j) in mem2:
                    continue
                else:
                    mem2[(i,j)]=lv
                if i>0 and j>0:
                    if word1[i-1]==word2[j-1]:
                        stack2.append((i-1,j-1,lv))
                        continue
                    else:
                        #rep
                        newstack2.append((i-1,j-1,lv+1))
                #add
                if j>0:
                    newstack2.append((i,j-1,lv+1))
                #del
                if i>0:
                    newstack2.append((i-1,j,lv+1))
            stack2=newstack2
相關文章
相關標籤/搜索