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])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章