leetcode刷题记录781-790 python版

前言

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

781. 森林中的兔子

class Solution:
    def numRabbits(self, answers: List[int]) -> int:
        answers.sort()
        res = 0
        while answers:
            x = answers.pop(0)
            same_color = x + 1
            res += same_color
            while answers and x==answers[0] and same_color>1:
                same_color -= 1
                answers.pop(0)
        return res

782. 变为棋盘

# 这题还没搞会,先记录一下大神解法
class Solution:
    def movesToChessboard(self, board: List[List[int]]) -> int:
        import collections
        # 判断初始矩阵是否合法(是否能转换为棋盘)
        h = collections.Counter(map(tuple, board))
        if len(h) != 2: return -1
        r1, r2 = h.keys()
        n = len(board)
        if abs(h[r1] - h[r2]) > 1 or abs(sum(r1) * 2 - n) > 1:  return -1
        for i in range(n):
            if r1[i] == r2[i]:  return -1

        # 求将一维01数组转换为交错数列所需的最小元素交换次数
        def minMoves(x):
            n, y = len(x), sum(x) > len(x) / 2
            count = sum([x[i] != y for i in range(0, n, 2)])
            return min(count, n // 2 - count if n % 2 == 0 else 100000)

        # 计算使得所有行(列)变成交错数列所需的列(行)交换次数
        return minMoves([board[i][0] for i in range(n)]) + minMoves(r1 if h[r1] > h[r2] else r2)

783. 二叉搜索树节点最小距离

class Solution:
    def minDiffInBST(self, root: TreeNode) -> int:
        res = self.helper(root)
        if len(res) < 2: return
        m = res[2] - res[1]
        for i in range(len(res) - 1):
            if res[i + 1] - res[i] < m:
                m = res[i + 1] - res[i]
        return m

    # 返回二叉搜索树中序遍历结果:递增数组
    def helper(self, root):
        if not root: return []
        else:
            return self.helper(root.left) + [root.val] + self.helper(root.right)

784. 字母大小写全排列

class Solution:
    def letterCasePermutation(self, S: str) -> list:
        res = []
        n = len(S)
        def backtrack(S, p):
            res.append(S)
            for k in range(p, n):
                if 'a' <= S[k] <= 'z':
                    backtrack(S[:k] + S[k].upper() + S[k + 1:], k + 1)
                elif 'A' <= S[k] <= 'Z':
                    backtrack(S[:k] + S[k].lower() + S[k + 1:], k + 1)
            return
        backtrack(S, 0)
        return res

785. 判断二分图

# 膜拜大佬
class Solution:
    def isBipartite(self, graph: List[List[int]]) -> bool:
        vis = [0] * len(graph)
        def dfs(pos, color):
            vis[pos] = color
            for i in graph[pos]:
                # 颜色相同 or (未访问 且 继续深搜为False)
                # 可直接返回False
                if vis[i] == color or not (vis[i] or dfs(i, -color)):
                    return False
            return True
        # 不一定为联通图,需遍历每一个节点
        for i in range(len(graph)):
            if not vis[i] and not dfs(i, 1):
                return False
        return True

786. 第 K 个最小的素数分数

class Solution:
    def kthSmallestPrimeFraction(self, A: List[int], K: int) -> List[int]:
        def count(x):
            i = 0
            cnt = 0
            for j in range(1, len(A)):
                while i < j and A[i] / A[j] <= x:
                    i += 1
                cnt += i
            return cnt
        EPS = 1e-9 # 二分。玄学精度,1e-8过不了
        l, r = A[0] / A[-1], 1
        while r - l > EPS:
            mid = (l + r) / 2
            if count(mid) >= K:
                r = mid
            else:
                l = mid
        # 浮点数转分数
        for b in A:
            a = round(l * b)
            # l 的精度是 EPS,l*b 就是 b*EPS
            if abs(a - l * b) < b * EPS:
                return a, b

787. K 站中转内最便宜的航班

class Solution(object):
    def findCheapestPrice(self, n, flights, src, dst, K):
        # dp[k][d] 记录经过k次转机后到达d城市的最小花费
        dp = [[float('inf')]*n for i in range(K+1)]
        # 初始化0次转机直达的花费
        for s,d,p in flights:
            if s == src :
                dp[0][d] = p
        for k in range(1,K+1):
            for s,d,p in flights:
                # 状态转移,第k次转机到达d城市的最小花费 = min (第k-1次转机到达d城市的最小花费,第k-1次转机到达s城市的最小花费 +s到达d的花费p,第k次转机到达d城市的最小花费)
                dp[k][d] = min(dp[k-1][d],dp[k-1][s]+p,dp[k][d])
        return dp[-1][dst] if dp[-1][dst] != float('inf') else -1

788. 旋转数字

class Solution:
    def rotatedDigits(self, N: int) -> int:
        res = 0
        d = [0, 0, 1, -1, -1, 1, 1, -1, 0, 1] + [0] * (N - 9)
        for i in range(N + 1):
            if d[i // 10] == -1 or d[i % 10] == -1:
                d[i] = -1
            elif d[i // 10] == 1 or d[i % 10] == 1:
                d[i] = 1
                res += 1
        return res

789. 逃脱阻碍者

# 一行
class Solution:
    def escapeGhosts(self, ghosts: List[List[int]], target: List[int]) -> bool:
        return all([abs(target[0])+abs(target[1]) < abs(ghost[0]-target[0])+abs(ghost[1]-target[1]) for ghost in ghosts])
# 谁近谁赢
class Solution:
    def escapeGhosts(self, ghosts: List[List[int]], target: List[int]) -> bool:
        steps = abs(target[0]) + abs(target[1])
        for x, y in ghosts:
            if abs(x - target[0]) + abs(y - target[1]) <= steps:
                return False
        return True

790. 多米诺和托米诺平铺

class Solution:
    def numTilings(self, N: int) -> int:
        a, b, total = 1, 2, 1 ##a,b,total 分别代表dp[i-2],dp[i-1],dp[k from 0 to i-3]
        if N == 1: return 1
        for i in range(3,N+1):
            tmp = b
            b += a+2*total  
            total += a
            a = tmp
        return b%(10**9+7)

你可能感兴趣的:(leetcode,leetcode,python)