leetcode刷题记录301-310 python版

前言

继续leetcode刷题生涯
这里记录的都是笔者觉得有点意思的做法
参考了好几位大佬的题解,尤其是powcai大佬和labuladong大佬,感谢各位大佬

301. 删除无效的括号

class Solution:
    def removeInvalidParentheses1(self, s: str):
        # 找字符串最长有效括号的长度
        def longestVaildParentheses(s: str):
            res = 0
            stack = []
            for a in s:
                if a == "(":
                    stack.append("(")
                elif a == ")":
                    if stack:
                        res += 2
                        stack.pop()
            return res
        # dfs
        def helper(s, left_p, right_p, open, tmp):
            # 当都小于0 都不满足条件
            if left_p < 0 or right_p < 0 or open < 0:
                return
            # s剩余的括号都不够组成的
            if s.count("(") < left_p or s.count(")") < right_p:
                return
            if not s:
                # 输出
                if left_p == 0 and right_p == 0 and open == 0:
                    res.add(tmp)
                return
            if s[0] == "(":
                # 用 "("
                helper(s[1:], left_p - 1, right_p, open + 1, tmp + "(")
                # 不用 "("
                helper(s[1:], left_p, right_p, open, tmp)
            elif s[0] == ")":
                # 用 ")"
                helper(s[1:], left_p, right_p - 1, open - 1, tmp + ")")
                # 不用 ")"
                helper(s[1:], left_p, right_p, open, tmp)
            else:
                helper(s[1:], left_p, right_p, open, tmp + s[0])
        l = longestVaildParentheses(s)
        res = set()
        # 因为l是最长的, 所以左括号和右括号各一半, 再用open表示左右括号抵消多少
        helper(s, l // 2, l // 2, 0, "")
        return list(res)

303. 区域和检索 - 数组不可变

class NumArray:
    def __init__(self, nums: List[int]):
        self.dp = [0]
        for num in nums:
            self.dp.append(self.dp[-1] + num)
    def sumRange(self, i: int, j: int) -> int:
        return self.dp[j + 1] - self.dp[i]

304. 二维区域和检索 - 矩阵不可变

class NumMatrix:
    def __init__(self, matrix: List[List[int]]):
        if not matrix or not matrix[0]:pass
        else:
            row = len(matrix)
            col = len(matrix[0])
            self.dp = [[ 0 ] * (col + 1) for _ in range(row + 1)]
            for i in range(1, row + 1):
                for j in range(1, col + 1):
                    self.dp[i][j] = matrix[i - 1][j - 1] + self.dp[i - 1][j] + self.dp[i][j - 1] - self.dp[i-1][j-1]
    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        return self.dp[row2 + 1][col2 + 1] - self.dp[row1][col2 + 1] - self.dp[row2 + 1][col1] + self.dp[row1][col1]

306. 累加数

# 递归
class Solution:
    def isAdditiveNumber(self, num: str) -> bool:
        def isValid(sub1, sub2, num):
            if not num: return True
            sub1, sub2 = sub2, str(int(sub1) + int(sub2))
            return num.startswith(sub2) and isValid(sub1, sub2, num[len(sub2):])

        n = len(num)
        for i in range(1, n // 2 + 1):
            if num[0] == "0" and i > 1: return False
            sub1 = num[:i]
            for j in range(1, n):
                # 剩下的长度都没有前面两个数最大长度长
                if max(i, j) > n - i - j: break
                if num[i] == "0" and j > 1: break
                sub2 = num[i: i + j]
                # 找到两个数, 看后面的数是否能引出来
                if isValid(sub1, sub2, num[i + j:]): return True
        return False
# 迭代
class Solution:
    def isAdditiveNumber(self, num: str) -> bool:
        def isValid(sub1, sub2, num):
            while num:
                sub1, sub2, = sub2, str(int(sub1) + int(sub2))
                if not num.startswith(sub2): return False
                num = num[len(sub2):]
            return True

        n = len(num)
        for i in range(1, n // 2 + 1):
            if num[0] == "0" and i > 1: return False
            sub1 = num[:i]
            for j in range(1, n):
                # 剩下的长度都没有前面两个数最大长度长
                if max(i, j) > n - i - j: break
                if num[i] == "0" and j > 1: break
                sub2 = num[i: i + j]
                # 找到两个数, 看后面的数是否能引出来
                if isValid(sub1, sub2, num[i + j:]): return True
        return False

307. 区域和检索 - 数组可修改

# 线段树
class NumArray:
    def __init__(self, nums):
        self.l = len(nums)
        self.tree = [0] * self.l + nums
        for i in range(self.l - 1, 0, -1):
            self.tree[i] = self.tree[i << 1] + self.tree[i << 1 | 1]
    def update(self, i, val):
        n = self.l + i
        self.tree[n] = val
        while n > 1:
            self.tree[n >> 1] = self.tree[n] + self.tree[n ^ 1]
            n >>= 1
    def sumRange(self, i, j):
        m = self.l + i
        n = self.l + j
        res = 0
        while m <= n:
            if m & 1:
                res += self.tree[m]
                m += 1
            m >>= 1
            if n & 1 == 0:
                res += self.tree[n]
                n -= 1
            n >>= 1
        return res

309. 最佳买卖股票时机含冷冻期

# 动态规划
# dp[i][0]表示在i天买入最大利益
# dp[i][1]表示在i天卖出最大利益
# dp[i][2]表示在经过卖出的后一天冷冻期的最大利益
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices: return 0
        n = len(prices)
        dp = [[0] * 3 for _ in range(n)]
        dp[0][0] = -prices[0]
        for i in range(1, n):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i])
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])
            dp[i][2] = dp[i - 1][1]
        return dp[-1][1]
# 这个动态规划有点妙

310. 最小高度树

# dfs 超时
class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        from collections import defaultdict
        if not edges: return [0]
        graph = defaultdict(list)
        # 记录每个节点最高的高度
        lookup = [0] * n
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)
        def dfs(i, visited, depth):
            lookup[i] = max(lookup[i], depth)
            for j in graph[i]:
                if j not in visited:
                    dfs(j, visited | {j}, depth + 1)
        leaves = [i for i in graph if len(graph[i]) == 1]
        for i in leaves:
            dfs(i, {i}, 1)
        min_num = min(lookup)
        return [i for i in range(n) if lookup[i] == min_num]
# bfs
class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        from collections import defaultdict
        if not edges: return [0]
        graph = defaultdict(list)
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)
        # 叶子节点,度为1
        leaves = [i for i in graph if len(graph[i]) == 1]
        while n > 2:
            n -= len(leaves)
            nxt_leaves = []
            for leave in leaves:
                # 与叶子节点相连的点找到
                tmp = graph[leave].pop()
                # 相连的点删去这个叶子节点
                graph[tmp].remove(leave)
                if len(graph[tmp]) == 1:
                    nxt_leaves.append(tmp)
            leaves = nxt_leaves
        return list(leaves)

你可能感兴趣的:(leetcode)