leetcode刷题记录671-680 python版

前言

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

671. 二叉树中第二小的节点

class Solution:
    def findSecondMinimumValue(self, root: TreeNode) -> int:
        import collections
        num = []
        def helpper(root):
            if root:
                num.append(root.val)
                helpper(root.left)
                helpper(root.right)
        helpper(root)
        numdict = collections.Counter(num)
        numdictorder = sorted(numdict)
        if len(numdictorder)<2:
            return -1
        return numdictorder[1]

672. 灯泡开关 Ⅱ

class Solution:
    def flipLights(self, n: int, m: int) -> int:
        if m == 0: return 1
        if n == 1: return 2
        if n == 2:
            if m == 1: return 3
            else: return 4
        if m == 1: return 4
        elif m == 2: return 7
        else: return 8

673. 最长递增子序列的个数

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 0:return 0
        dp = [1]*n
        for i in range(1,n):
            if nums[i] == nums[i-1]:
                dp[i] = dp[i-1]
                continue
            else:
                for j in range(i-1,-1,-1):
                    if nums[i] > nums[j] and dp[j]+1 > dp[i]:
                        dp[i] = dp[j]+1
        mindp = min(dp)
        maxdp = max(dp)
        if maxdp == mindp:return n
        dp2 = [1]*n
        for i in range(1,n):
            if dp[i] == mindp:
                dp2[i]=1
                continue
            count=0
            for j in range(i):
                if dp[j] == dp[i]-1 and nums[j] < nums[i]:
                    count += dp2[j]
            dp2[i] = count
        res=0
        for i in range(n):
            if dp[i] == maxdp: res += dp2[i]
        return res

674. 最长连续递增序列

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        n = len(nums)
        if n <= 1: return n
        res = 0
        cnt = 1
        for i in range(1, n):
            if nums[i] > nums[i-1]:
                cnt += 1
            else:
                cnt = 1
            res = max(res, cnt)
        return res

675. 为高尔夫比赛砍树

# 笔者没做出来,题解里有个优化做的很好的如下
class Que:  # 自己实现效率更高的队列操作
    def __init__(self, len) -> int:
        self.q = [0] * len
        self.h, self.t = 0, 0  # 头、尾指针

    def isNull(self) -> bool:
        return self.h == self.t

    def reset(self):
        self.h, self.t = 0, 0

    def push(self, val):
        self.q[self.t] = val
        self.t += 1

    def pop(self):
        if self.isNull():
            return None
        else:
            ret = self.q[self.h]
            self.h += 1
            return ret


class Solution:
    def cutOffTree(self, forest: List[List[int]]) -> int:
        m, n = len(forest), len(forest[0])
        self.go = [1, -1, n + 2, - n - 2]
        woods = [
            forest[i // (n + 2) - 1][i % (n + 2) - 1] if 0 < i // (n + 2) < m + 1 and 0 < i % (n + 2) < n + 1 else 0 for
            i in range((m + 2) * (n + 2))]  # 二维转一维操作
        hl = []
        for i, h in enumerate(woods):
            if h > 0: hl.append((h, i))
        hl = sorted(hl)
        if len(hl) > 0 and hl[0] != n + 3:
            hl.insert(0, (0, n + 3))
        qu = Que(3000)

        def astar(s, d1, d2, w, qu) -> int:
            qu.reset()
            sele = [False] * len(w)
            res1, res2, step = 0, 0, 0
            r1, r2 = False, False
            if d1 == s: r1 = True
            if d2 == s or d2 == 0: r2 = True
            qu.push((s, 0))
            sele[s] = True
            while not qu.isNull() and not (r1 and r2):  # 减枝
                val = qu.pop()
                for k in self.go:
                    idx = val[0] + k
                    if 0 != w[idx] and not sele[idx]:  # 减枝
                        if not r1 and d1 == idx:
                            r1 = True
                            res1 = val[1] + 1
                        if not r2 and d2 == idx:
                            r2 = True
                            res2 = val[1] + 1
                        qu.push((idx, val[1] + 1))
                        sele[idx] = True
            return res1 + res2 if r1 and r2 else -1

        res = 0
        for i in range(1, len(hl), 2):  # 跳跃BFS
            r = astar(hl[i][1], hl[i - 1][1], hl[i + 1][1] if i < len(hl) - 1 else 0, woods, qu)
            if -1 == r: return -1
            res += r
        return res

676. 实现一个魔法字典

class MagicDictionary:
    def __init__(self):
        self.d = {}

    def buildDict(self, dict: List[str]) -> None:
        for word in dict:
            p = self.d
            for c in word + '$':
                if c not in p:
                    p[c] = {}
                p = p[c]

    def search(self, word: str) -> bool:
        word += '$'
        import collections
        q = collections.deque([(self.d, False)])
        for c in word:
            for _ in range(len(q)):
                node, modified = q.popleft()
                if c in node:
                    q += [(node[c], modified)]
                if not modified:
                    q += [(node[k], True) for k in node if k != c]
        for node, modified in q:
            if node == {} and modified:
                return True
        return False

677. 键值映射

class MapSum:
    def __init__(self):
        self.d = {}

    def insert(self, key: str, val: int) -> None:
        self.d[key] = val

    def sum(self, prefix: str) -> int:
        return sum(self.d[s] for s in self.d if s.startswith(prefix))

678. 有效的括号字符串

class Solution(object):
    def checkValidString(self, strs):
        n = len(strs)
        num = 0
        for i in range(n):
            if strs[i] == ')':
                num -= 1
            else:
                num += 1
            if num < 0:
                return False
        num = 0
        for i in range(n-1, -1, -1):
            if strs[i] == '(':
                num -= 1
            else:
                num += 1
            if num < 0:
                return False
        return True

679. 24 点游戏

# 暴力递归
class Solution:
    def judgePoint24(self, nums: List[int]) -> bool:
        if not nums: return False
        def helper(nums):
            if len(nums) == 1: return abs(nums[0]-24) < 1e-6
            for i in range(len(nums)):
                for j in range(i + 1, len(nums)):
                    newnums = [nums[k] for k in range(len(nums)) if i != k != j]
                    if helper(newnums + [nums[i]+nums[j]]): return True
                    if helper(newnums + [nums[i]*nums[j]]): return True
                    if helper(newnums + [nums[i]-nums[j]]): return True
                    if helper(newnums + [nums[j]-nums[i]]): return True
                    if nums[j] != 0 and helper(newnums + [nums[i]/nums[j]]): return True
                    if nums[i] != 0 and helper(newnums + [nums[j]/nums[i]]): return True
            return False
        return helper(nums)

680. 验证回文字符串 Ⅱ

class Solution:
    def validPalindrome(self, s: str) -> bool:
        ## 本身是回文字符串时,返回True
        r = s[::-1]
        if s == r: return True
        ## 本身不是回文字符串时,利用切片生成子字符串,判断其是否回文字符串
        ## 利用双指针,在生成子字符串时,既可以删除左指针指向的字符,也可以删除右指针指向的字符。
        i, j =0, len(s)-1
        while True:     # 由于本身不是回文字符串,if语句必然执行产生return
            if s[i] != s[j]:
                ## 由于这样切片s[i+1:j+1]在j=len(s)-1时会出错,改为s[i+1:j]+s[j]
                return s[i:j] == r[i+1:j]+r[j] or s[i+1:j]+s[j] == r[i:j]
            i += 1
            j -= 1

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