leetcode 刷题动态规划系列(1)

最长回文子串

class Solution:
    def longestPalindrome(self, s: str) -> str:
        ans = ''
        n = len(s)
        dp = [[0] * n for _ in range(n)]
        max_len = float("-inf")
        for i in range(n):
            for j in range(i, -1, -1):
                if s[i] == s[j] and (i - j < 2 or dp[i - 1][j + 1]):
                    dp[i][j] = 1
                if dp[i][j] and i - j + 1 > max_len:
                    max_len = i - j + 1
                    ans = s[j:i + 1]
        return ans

最大子序和

class Solution:
    def maxSubArray(self, nums) -> int:
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        res = nums[0] 
        for i in range(1, len(nums)):
            nums[i] = max(nums[i], nums[i] + nums[i - 1])  
            res = max(res, nums[i]) 
        return res
  1. 不同路径
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        dp = [[0]*n]*m
        for i in range(m):
            for j in range(n):
                if i ==0 or j == 0:
                    dp[i][j] = 1
                else:
                    dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[-1][-1]                 

不同路径 II

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m = len(obstacleGrid[0])
        n = len(obstacleGrid)
        dp = [[0]*m for _ in range(n)]
        if obstacleGrid[0][0] == 1:
                return 0
        dp[0][0] = 1
        for i in range(1,n):
            if obstacleGrid[i][0] == 1:
                dp[i][0] = 0
                break
            else:
                dp[i][0] = 1
        for j in range(1, m):
            if obstacleGrid[0][j] == 1:
                dp[0][j] = 0
                break
            else:
                dp[0][j] = 1
        for l in range(1,n):
            for r in range(1,m):
                if obstacleGrid[l][r]==1:
                    dp[l][r] = 0
                else:
                    dp[l][r] = dp[l-1][r] + dp[l][r-1]
        return dp[-1][-1] 

91解码方法

class Solution:
    def numDecodings(self, s: str) -> int:
        if not s or s[0] == '0':
            return 0
        dp = [1, 1]
        for i in range(1,len(s)):
            if  s[i] == '0':
                if s[i-1] == '1' or s[i-1] == '2':
                    dp.append(dp[-2])
                else:
                    return 0     
            elif  s[i-1] == '1' or (s[i-1] == '2' and  s[i] <= '6'):
                  dp.append(dp[-1]+dp[-2])
            else:
                  dp.append(dp[-1])
        return dp[-1]  
  1. 不同的二叉搜索树 II
class Solution:
    def generateTrees(self, n: int) -> List[TreeNode]:
        if(n==0):
            return []
        def build_Trees(left,right):
            all_tree = []
            if left > right :
               return [None] 
            for i in range(left,right+1):
                left_tree = build_Trees(left,i-1)
                right_tree = build_Trees(i+1,right)
                for l in left_tree:
                    for r in right_tree:
                        cur_tree = TreeNode(i)
                        cur_tree.left = l
                        cur_tree.right = r
                        all_tree.append(cur_tree)
            return all_tree            
        res=build_Trees(1,n)
        return res
  1. 单词拆分
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        n = len(s)   
        dp = [False] * (n+1)
        dp[0] = True
        for i in range(n):
            for j in range(i+1,n+1):
                if  dp[i] and (s[i:j] in wordDict):
                    dp[j] = True
        return dp[-1]   
  1. 最大正方形
class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        if(not matrix):
            return 0
        m=len(matrix)
        n=len(matrix[0])
        res=0
        dp=[[0]*(n+1) for _ in range(m+1)]
        for i in range(1,m+1):
            for j in range(1,n+1):
                if  matrix[i-1][j-1] == "1":
                    dp[i][j]=min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1
                    res=max(dp[i][j],res)
        return res*res
  1. 完全平方数
class Solution:
    def numSquares(self, n: int) -> int:
        queue = [n]
        step = 0
        visited = set()
        while queue:
            step+=1
            stack = []
            l=len(queue)
            for _ in range(l):
                tmp = queue.pop(0)
                for i in range(1,int(tmp**0.5)+1):
                    x=tmp-i**2
                    if (x==0):
                        return step
                    if (x not in visited):
                        stack.append(x)
                        visited.add(x)
            queue = stack
        return step
  1. 最长上升子序列
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums: return 0
        dp = [1] * len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if  nums[j] < nums[i]:
                    dp[i] = max(dp[i], dp[j] + 1)
        return  max(dp)
  1. 最佳买卖股票时机含冷冻期
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices: return 0
        n = len(prices)
        buy = [0] * n
        sell  = [0] * n
        buy[0] = - prices[0]
        for i in range(1,n):
            if  i >= 2:
                buy[i] = max(buy[i-1],sell[i-2]- prices[i])
            else:
                buy[i] = max(buy[i-1], sell[i-1] - prices[i])    
            sell[i] = max(sell[i-1],buy[i-1]+prices[i])
        return max(sell)  
  1. 整数拆分
class Solution:
    def integerBreak(self, n: int) -> int:
        dp = [0] * (n+1)
        for i in range(2,n+1):
            for j in range(i):
                dp[i] = max(dp[i],j*(i-j) ,j *dp[i-j])
        return dp[-1]        
  1. 最大整除子集
class Solution:
    def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
        if not nums: 
           return []
        nums.sort()
        n = len(nums)       
        lookup = {
     }
        for num in nums:
            t = [num]
            for sp in lookup:
                if num % sp == 0 and len(lookup[sp]) + 1 >len(t): 
                   t = lookup[sp]+[num]
            lookup[num] = t
        return max(lookup.values(), key=len)
  1. 摆动序列
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        n = len(nums)
        if n < 2: 
           return n
        up = [1] * n
        down = [1] * n 
        for i in range(1,n):
            if  nums[i] > nums[i-1]:
                up[i],down[i] = down[i-1] + 1 ,down[i-1]
            elif nums[i] < nums[i-1]:
                up[i],down[i] = up[i-1],  up[i-1] + 1
            else:    
                up[i],down[i] = up[i-1],down[i-1]
        return max(up[-1],down[-1])        
  1. 组合总和 Ⅳ
class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:
        n = target
        dp = [1]+ [0]*(n)
        for i in range(n+1):
            for num in nums:
                if  i >= num:
                    dp[i] += dp[i - num] 
        return dp[-1]    
  1. 等差数列划分
class Solution:
    def numberOfArithmeticSlices(self, A: List[int]) -> int:
        n = len(A)
        dp = [0] * n
        for i in range(2,n):
            if A[i-1] - A[i-2] == A[i]-A[i-1]:
               dp[i] = dp[i-1] + 1 
        return sum(dp)       
  1. 分割等和子集
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        nums.sort()
        sums = sum(nums)
        if sums % 2 == 1:
            return False
        res = sums // 2
        n = len(nums)
        dp = [[0]*(res+1) for _ in range(n)]
        for i in range(0,n):
            for j in range(res+1):
                if nums[i] == j :
                    dp[i][j] = 1
                    continue
                if nums[i] < j :
                    dp[i][j] = dp[i - 1][j] or dp[i - 1][j - nums[i]]
        return dp[-1][-1]
  1. 环绕字符串中唯一的子字符串
class Solution:
    def findSubstringInWraproundString(self, p: str) -> int:
        if len(p) == 0:
            return 0
        n = len(p)
        dp = [0] * 26
        dp[ord(p[0])-ord('a')] = 1
        k = 1
        for i in range(1,n):
            if (ord(p[i])-ord(p[i-1])) %26 ==1:
                k += 1
                dp[ord(p[i])-ord('a')] = max(k,dp[ord(p[i])-ord('a')])
            else:
                k = 1
                if  dp[ord(p[i]) -  ord('a')] ==0:
                    dp[ord(p[i]) -  ord('a')] = 1
        return sum(dp)
  1. 目标和
class Solution:
    def findTargetSumWays(self, nums, S: int) -> int:
        sum_n = sum(nums)
        if (sum_n+S)%2!=0 or sum_n<S:
            return 0
        m =  (S+sum_n)//2   
        return self.dp(nums,m)
    def dp(self,nums,m):
        dps = [0]*(m+1)
        dps[0] = 1
        for sp in nums:
            for j in range(m,sp-1,-1):
                dps[j] += dps[j-sp]
        print(dps[m])
        return dps[m]
  1. 最长重复子数组
class Solution:
    def findLength(self, A: List[int], B: List[int]) -> int:
        n,m = len(A),len(B)
        dp = [[0]*(m+1) for _ in range(n+1)]
        for i in range(n-1,-1,-1):
            for j in range(m-1,-1,-1):
                if  A[i] == B[j]:
                    dp[i][j] = dp[i+1][j+1] + 1
        return  max(max(row) for row in dp)
  1. 使用最小花费爬楼梯
class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        n = len(cost)
        dp = [0]*(n+1)
        dp[0],dp[1] = 0,0
        for i in range(2,n+1):
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
        return dp[-1]    
  1. 最长的斐波那契子序列的长度
import collections
class Solution(object):
    def lenLongestFibSubseq(self, A):
        index = {
     x: i for i, x in enumerate(A)}
        longest = collections.defaultdict(lambda: 2)
        ans = 0
        for k, z in enumerate(A):
            for j in range(k):
                i = index.get(z - A[j], None)
                if i is not None and i < j:
                    cand = longest[j, k] = longest[i, j] + 1
                    ans = max(ans, cand)
        return ans if ans >= 3 else 0
  1. 最长湍流子数组
class Solution:
    def maxTurbulenceSize(self, A: List[int]) -> int:
        if len(A) == 1:
            return 1
        nums = []
        for i in range(1,len(A)):
            ss = A[i] - A[i-1]
            nums.append(1 if ss >0 else 0 if ss==0 else -1)
        print(nums)
        dp = [0] * len(nums)
        dp[0] = 0 if nums[0] == 0 else 1
        for i in range(1,len(nums)):
            if nums[i] == 0:
                 dp[i] = 0
            elif nums[i] + nums[i-1] == 0:
                 dp[i] = dp[i-1] + 1
            else:
                 dp[i] = 1
        return max(dp)+1                     

你可能感兴趣的:(东北大学,动态规划,leetcode)