1. 程式人生 > >leetcode312. Burst Balloons/96. Unique Binary Search Trees

leetcode312. Burst Balloons/96. Unique Binary Search Trees

題目描述

給定n個氣球,索引0…n-1,每個氣球上標有數字。你需要戳破所有的氣球。如果你戳破了氣球i,你將得到nums[i-1] * nums[i] * nums[i+1]個金幣。戳破後i-1會和i+1相鄰。 輸出可得到的最大金幣數。

你可以假設nums[-1] = nums[n] = 1。它們並不是真實存在的,所以無需戳破它們。 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100。

例子

Input: [3,1,5,8] Output: 167

Explanation: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

思想 (DP) dp[i][j]表示戳破從第i到第j個氣球得到的最大金幣數。 我們標記x是最後一個被戳破的氣球,則最後一次得到的金幣數為nums[i-1] * nums[x] * nums[j+1] 狀態方程: dp[i][j] = max(dp[i][j], dp[i][x – 1] + nums[i – 1] * nums[x] * nums[j + 1] + dp[x + 1][j]) 複雜度:時間 - O(n**3),空間 - O(n**2) 解法1 定義gap為i到j的長度,i和j都是從1…n,則i+gap≤n → i≤n-gap

class Solution(object):
    def
maxCoins(self, nums): """ :type nums: List[int] :rtype: int """ n = len(nums) nums = [1] + nums + [1] dp = [[0] * (n+2) for _ in range(n+2)] for gap in range(n): # The length of i-to-j for i in range(1, n-gap+1):
# 1...n j = i + gap for x in range(i, j+1): dp[i][j] = max(dp[i][j], dp[i][x-1] + nums[i-1] * nums[x] * nums[j+1] + dp[x+1][j]) return dp[1][n]

解法2 記憶化搜尋,更容易理解。

class Solution(object):
    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        nums = [1] + nums + [1]
        dp = [[0] * (n+2) for _ in range(n+2)]
        
        def helper(i, j):
            if dp[i][j] > 0:
                return dp[i][j]
            for x in range(i, j+1):
                dp[i][j] = max(dp[i][j], helper(i, x-1) + nums[i-1] * nums[x] * nums[j+1] + helper(x+1, j))
            return dp[i][j]
        
        return helper(1, n)

題目描述

給定n,有多少個不同的二叉搜尋樹(儲存值1…n)

例子

Input: 3 Output: 5

思想 1…n都可以作為二叉搜尋樹的根節點,當k是根節點時,它的左邊有k-1個不等的數,它的右邊有n-k個不等的數。以k為根節點的二叉搜尋樹的種類就是左右可能的種類的乘積。 用遞推式表示就是 h(n) = h(0)*h(n-1) + h(1)*h(n-2) + … + h(n-1)h(0) (其中n>=2) ,其中h(0)=h(1)=1,因為0個或者1個數能組成的形狀都只有一個。從1到n依次算出h(x)的值即可。

解法1 複雜度:時間 - O(n**2)

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [0] * (n+1)
        dp[0] = 1 
        for i in range(1, n+1):
            for j in range(i):
                dp[i] += dp[j] * dp[i-j-1]
        return dp[-1]

解法2 記憶化搜尋

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [0] * (n+1)
        
        def helper(m):
            if m <= 1:
                return m
            if dp[m] > 0:
                return dp[m]
            for i in range(m):
                left = helper(i)
                right = helper(m-i-1)
                if left == 0 or right == 0:
                    dp[m] += left + right
                else:
                    dp[m] += left * right
            return dp[m]
        
        return helper(n)