今晚写了几题简单的动态规划。

##70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

### 时间复杂度: O (N)
### 空间复杂度:用数组记录 O (n), 用 p1, p2 循环 O (1)

class Solution:
    def climbStairs(self, n: int) -> int:
        #p[i] = p[i-1] + p[i-2]
        if n==1:
            return 1
        if n==2:
            return 2
        # p = [0] * n
        # p[0] = 1
        # p[1] = 2
        # for i in range(2, n):
        #     p[i] = p[i-1] + p[i-2]
        # return p[i]
        p1 = 1
        p2 = 2
        for i in range(2, n):
            p2, p1 = p2+p1, p2
        return p2

##198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

### 时间复杂度: O (N)
### 空间复杂度:用数组记录 O (n)

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums)==1:
            return nums[0]
        if len(nums)==2:
            return max(nums[0], nums[1])
        # dp[i] = max(dp[i-1], dp[i-2]+nums[i])
        dp = [0] * len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, len(nums)):
            dp[i] = max(dp[i-1], dp[i-2]+nums[i])
        return dp[-1] 

##139. 单词拆分
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释:返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。

### 时间复杂度: O (N2)* 字符串查找
### 空间复杂度:用数组记录 O (n)

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        # dp[x] = {dp[i] + isinword(s[i:x])}
        n = len(s)
        # dp[i]表示s的前i位是否可以用wordDict中的单词表示
        dp = [False] * (n+1)
        # 初始化dp[0]=True,空字符可以被表示
        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]