LeetCode每日一题8月记录

8.1 最小区间

原题地址.
变相的用滑动窗口法求解,统计每个数字出现在输入的哪几个数组里面,然后利用双指针滑动窗口寻找最小的左右边界,使得全部数组都有这些元素。

class Solution:
    def smallestRange(self, nums: List[List[int]]) -> List[int]:
        n = len(nums)
        indices = collections.defaultdict(list)
        xMin, xMax = 10**9, -10**9
        for i, vec in enumerate(nums):
            for x in vec:
                indices[x].append(i)
            xMin = min(xMin, *vec)
            xMax = max(xMax, *vec)

        freq = [0] * n
        inside = 0
        left, right = xMin, xMin - 1
        bestLeft, bestRight = xMin, xMax

        while right < xMax:
            right += 1
            if right in indices:
                #新加入统计右边界元素出现的list
                for x in indices[right]:
                    freq[x] += 1
                    #首次出现计数
                    if freq[x] == 1:
                        inside += 1
                while inside == n:
                    if right - left < bestRight - bestLeft:
                        bestLeft, bestRight = left, right
                    if left in indices:
                        for x in indices[left]:
                            freq[x] -= 1
                            #减到0推出窗口
                            if freq[x] == 0:
                                inside -= 1
                    left += 1

        return [bestLeft, bestRight]

8.2 二叉树展开为链表

原题地址.
递归处理,每次把左子树交换到右子树,把原来的右子树摘出来挂到左子树的最右儿子上,再处理下一层树。

class Solution:
    def flatten(self, root: TreeNode) -> None:
        if not root:
            return
        temp = root.right
        root.right = root.left
        root.left = None
        curr = root
        while curr.right:
            curr = curr.right
        curr.right = temp
        if root.right:
            self.flatten(root.right)
        return

8.3字符串相加

原题地址.
模拟实际加法,从右到左相加进位。

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i, j, carry = len(num1) - 1, len(num2) - 1, 0
        while i >= 0 or j >= 0 or carry:
            n1 = int(num1[i]) if i >= 0 else 0
            n2 = int(num2[j]) if j >= 0 else 0
            tmp = n1 + n2 + carry
            carry = tmp // 10
            res = str(tmp % 10) + res
            i, j = i - 1, j - 1
        return res

8.4 课程表

原题地址.
先统计好每个课程的依赖关系,再依次消去没有以来的课程,看最后剩余与否。

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        indegrees = [0 for _ in range(numCourses)]
        adjacency = [[] for _ in range(numCourses)]
        queue = []
        # 统计每个课程的出入度信息
        for cur, pre in prerequisites:
            indegrees[cur] += 1
            adjacency[pre].append(cur)

		#队列初始
        for i in range(len(indegrees)):
            if not indegrees[i]: queue.append(i)
        
        while queue:
            pre = queue.pop()
            numCourses -= 1
            #消去课程时,处理对应的依赖
            for cur in adjacency[pre]:
                indegrees[cur] -= 1
                if not indegrees[cur]: queue.append(cur)
        return not numCourses

8.5 打家劫舍Ⅲ

原题地址.
采用递归求解

class Solution:
    
    def dp(self , cur : TreeNode) -> List[int] :  
        #返回数组[不打劫当前根节点的最大收益,打劫根节点的最大收益]
        if not cur :
            return [0,0]
        l = self.dp(cur.left)
        r = self.dp(cur.right)
        #注意返回值的第一项,不打劫cur的话,l和r的选择就是自由的,可以选择俩者最大值
        return [max(l)+max(r),cur.val+l[0]+r[0]]
        
    def rob(self, root: TreeNode) -> int:
        return max(self.dp(root))

8.6 回文对

原题地址.
利用hash表减少枚举操作,使得快速查找有无对应字符串。

class Solution:
    def palindromePairs(self, words: List[str]) -> List[List[int]]:

        def findWord(s: str, left: int, right: int) -> int:
            return indices.get(s[left:right+1], -1)
        
        def isPalindrome(s: str, left: int, right: int) -> bool:
            return (sub := s[left:right+1]) == sub[::-1]
        
        n = len(words)
        #字符串倒序和index构成的hash表
        indices = {
   word[::-1]: i for i, word in enumerate(words)}
        
        ret = list()
        for i, word in enumerate(words):
            m = len(word)
            for j in range(m + 1):
                #后面是回文,寻找前半段是否存在
                if isPalindrome(word, j, m - 1):
                    leftId = findWord(word, 0, j - 1)
                    if leftId != -1 and leftId != i:
                        ret.append([i, leftId])
                #前半段回文,搜索后半段是否存在
                if j and isPalindrome(word, 0, j - 1):
                    rightId = findWord(word, j, m - 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值