leetcode刷题记录391-400 python版

前言

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

391. 完美矩形

class Solution:
    def isRectangleCover(self, rectangles: List[List[int]]) -> bool:
        # 保存所有矩形的四个点
        lookup = set()
        # 最大矩形的 左下角 右上角
        x1 = float("inf")
        y1 = float("inf")
        x2 = float("-inf")
        y2 = float("-inf")
        area = 0
        for x, y, s, t in rectangles:
            x1 = min(x1, x)
            y1 = min(y1, y)
            x2 = max(x2, s)
            y2 = max(y2, t)
            area += (t - y) * (s - x)
            # 每个矩形的四个点
            for item in [(x, y), (x, t), (s, y), (s, t)]:
                if item not in lookup:
                    lookup.add(item)
                else:
                    lookup.remove(item)
        # 只剩下四个点并且是最大矩形的左下角和右上角
        if len(lookup) != 4 or (x1, y1) not in lookup or (x1, y2) not in lookup or (x2, y1) not in lookup or (x2, y2) not in lookup:
            return False
        # 面积是否满足
        return (x2 - x1) * (y2 - y1) == area

392. 判断子序列

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        i = 0
        j = 0
        while i < len(s) and j < len(t):
            if s[i] == t[j]:
                i += 1
                j += 1
            else:
                j += 1
        return i == len(s)

393. UTF-8 编码验证

class Solution:
    def validUtf8(self, data: List[int]) -> bool:
        if not data: return False
        cnt = 0
        for d in data:
            if cnt == 0:
                if d >> 5 == 0b110:
                    cnt = 1
                elif d >> 4 == 0b1110:
                    cnt = 2
                elif d >> 3 == 0b11110:
                    cnt = 3
                elif d >> 7 != 0:
                    return False
            else:
                if d >> 6 != 0b10: return False
                cnt -= 1
        return cnt == 0

394. 字符串解码

class Solution:
    def decodeString(self, s: str) -> str:
        pos = 0
        def helper():
            nonlocal pos
            num = 0
            word = ""
            while pos < len(s):
                cur = s[pos]
                if cur == '[':
                    pos += 1
                    curStr = helper()
                    word += num * curStr
                    num = 0
                elif cur.isdigit():
                    num = num * 10 + int(cur)
                elif cur == ']':
                    return word
                else:
                    word += cur
                pos += 1
            return word
        return helper()

395. 至少有K个重复字符的最长子串

class Solution:
    def longestSubstring(self, s: str, k: int) -> int:
        if len(s) < k:
            return 0
        # 找个字符串个数最少的字符
        t = min(set(s), key=s.count)
        # 最少字符的个数都大于等于k
        if s.count(t) >= k:
            return len(s)
        return max(self.longestSubstring(a,k) for a in s.split(t))

396. 旋转函数

# F(k)=F(k−1)+sum(A)−len(A)∗A[len(A)−k]
class Solution:
    def maxRotateFunction(self, A: List[int]) -> int:
        n = len(A)
        cur = sum(A[i] * i for i in range(n))
        _sum = sum(A)
        res = cur
        for i in range(1, n):
            cur = _sum - n * A[-i] + cur
            res = max(res, cur)
        return res

397. 整数替换

# 规律
class Solution:
    def integerReplacement(self, n: int) -> int:
        step = 0
        while n > 1:
            if n & 1 == 0: n >>= 1
            elif (n + 1) % 4 == 0 and n != 3: n += 1
            else:
                n -= 1
            step += 1
        return step
# 递归,这里很妙的是带记忆,这个函数笔者之前都没接触过
from functools import lru_cache
class Solution:
    @lru_cache
    def integerReplacement(self, n: int) -> int:
        if n == 1:
            return 0
        if n % 2 == 0:
            return self.integerReplacement(n // 2) + 1
        else:
            return min(self.integerReplacement(n + 1), self.integerReplacement(n - 1)) + 1

398. 随机数索引

# 蓄水池采样
import random
class Solution:
    def __init__(self, nums):
        self.nums = nums
    def pick(self, target: int) -> int:
        count = 0
        res = -1
        for i in range(len(self.nums)):
            if self.nums[i] == target:
                if random.randint(0, count) < 1:  # 以某一概率(1/count)抽样
                    res = i
                count += 1
        return res

399. 除法求值

class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        # 构造图,equations的第一项除以第二项等于value里的对应值,第二项除以第一项等于其倒数
        graph = {}
        for (x, y), v in zip(equations, values):
            if x in graph:
                graph[x][y] = v
            else:
                graph[x] = {y: v}
            if y in graph:
                graph[y][x] = 1 / v
            else:
                graph[y] = {x: 1 / v}
        # dfs找寻从s到t的路径并返回结果叠乘后的边权重即结果
        def dfs(s, t) -> int:
            if s not in graph:
                return -1
            if t == s:
                return 1
            for node in graph[s].keys():
                if node == t:
                    return graph[s][node]
                elif node not in visited:
                    visited.add(node)  # 添加到已访问避免重复遍历
                    v = dfs(node, t)
                    if v != -1:
                        return graph[s][node] * v
            return -1
        # 逐个计算query的值
        res = []
        for qs, qt in queries:
            visited = set()
            res.append(dfs(qs, qt))
        return res

400. 第N个数字

class Solution:
    def findNthDigit(self, n: int) -> int:
        if n < 10: return n
        # 个数
        num = 9
        # 位数
        digit = 1
        while n - num * digit > 0:
            # 个数 * 位数 == 总数字个数
            n -= num * digit
            num *= 10
            digit += 1
        a, b = divmod(n - 1, digit)
        return int(str(10 ** (digit - 1) + a)[b])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章