【5月】LeetCode:我怎么还是这么菜

5.3

题目链接

53. 最大子序和

很喜欢的解法(DP)

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        maxSum=nums[0]
        tmp=0
        for i in nums:
            tmp=max(tmp+i,i)
            maxSum=max(maxSum,tmp)
        return maxSum

官方解(分治)

参考题解:最大子序和

但是仔细观察「方法二」,它不仅可以解决区间 [0,n−1],还可以用于解决任意的子区间 [l,r] 的问题。如果我们把 [0,n−1] 分治下去出现的所有子区间的信息都用堆式存储的方式记忆化下来,即建成一颗真正的树之后,我们就可以在 O(logn) 的时间内求到任意区间内的答案,我们甚至可以修改序列中的值,做一些简单的维护,之后仍然可以在 O(logn) 的时间内求到任意区间内的答案,对于大规模查询的情况下,这种方法的优势便体现了出来。这棵树就是上文提及的一种神奇的数据结构——线段树。

参考题解:【五种解法三种语言】(Java, JavaScript, Python)

import sys
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        return self.helper(nums, 0, len(nums) - 1)
    def helper(self, nums, l, r):
        if l > r:
            return -sys.maxsize
        mid = (l + r) // 2
        left = self.helper(nums, l, mid - 1)
        right = self.helper(nums, mid + 1, r)
        left_suffix_max_sum = right_prefix_max_sum = 0
        sum = 0
        for i in reversed(range(l, mid)):
            sum += nums[i]
            left_suffix_max_sum = max(left_suffix_max_sum, sum)
        sum = 0
        for i in range(mid + 1, r + 1):
            sum += nums[i]
            right_prefix_max_sum = max(right_prefix_max_sum, sum)
        cross_max_sum = left_suffix_max_sum + right_prefix_max_sum + nums[mid]
        return max(cross_max_sum, left, right)

5.4

题目链接

45. 跳跃游戏 II

官方解(贪心)

如果我们「贪心」地进行正向查找,每次找到可到达的最远位置,就可以在线性时间内得到最少的跳跃次数。
例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。

class Solution:
    def jump(self, nums: List[int]) -> int:
        n = len(nums)
        maxPos, end, step = 0, 0, 0
        for i in range(n - 1):
            if maxPos >= i:
                maxPos = max(maxPos, i + nums[i])
                if i == end:
                    end = maxPos
                    step += 1
        return step

自己有参考的解法

# 之前看评论,说用if比用max好像要快些……
class Solution:
    def jump(self, nums: List[int]) -> int:
        count=0
        begin,end=0,0
        while end<len(nums)-1:
            nowmax=end
            for i in range(begin,end+1):
                if i+nums[i]>nowmax:
                    nowmax=i+nums[i]
            begin,end=end+1,nowmax
            count+=1
        return count

5.6

题目链接

983. 最低票价

很喜欢的解法(DP,从前向后)

参考题解:【熊猫刷题Python3】一维动态规划,易懂(附视频题解)

对于一年中的任意一天:
首先考虑当前天数是否在 days 中,如果不在,那我们可以贪心地选择不买。这是因为如果今天不用出行,那么也不必购买通行证,并且通行证越晚买越好。
如果在的话,我们就要从三种购买方式中选择一种花费费用最少的,即如果想到达第 i 天,就需要从 i 的前1或7或30天的后一位置花费对应cost[0]、cost[1]、cost[2]的钱才能到第 i 天。

class Solution:
    def mincostTickets(self, days: List[int], costs: List[int]) -> int:
        dp=[0 for i in range(days[-1]+1)]
        index=0
        for i in range(days[0],len(dp)):
            if i!=days[index]:
                dp[i]=dp[i-1]
            else:
                dp[i]=min(dp[max(0,i-1)]+costs[0],dp[max(0,i-7)]+costs[1],dp[max(0,i-30)]+costs[2])
                index+=1
        return dp[-1]

官方解(DP,从后向前)

我们用 dp(i) 来表示从第 i 天开始到一年的结束,我们需要花的钱。考虑到一张通行证可以让我们在「接下来」的若干天进行旅行,所以我们「从后往前」倒着进行动态规划。
但是观察方法一的递推式,我们可以看到,如果我们查询 dp(i),而第 i 天我们又不需要出行的话,那么 dp 函数会一直向后计算 dp(i+1)=dp(i+2)=dp(i+3) 一直到一年结束或者有一天我们需要出行为止。那么我们其实可以直接跳过这些不需要出行的日期,直接找到下一个需要出行的日期。

class Solution:
    def mincostTickets(self, days: List[int], costs: List[int]) -> int:
        N = len(days)
        durations = [1, 7, 30]
        @lru_cache(None)
        def dp(i):
            if i >= N:
                return 0
            ans = 10**9
            j = i
            for c, d in zip(costs, durations):
                while j < N and days[j] < days[i] + d:
                    j += 1
                ans = min(ans, dp(j) + c)
            return ans
        return dp(0)

5.7

题目链接

572. 另一个树的子树

很喜欢的解法(递归判断子树)

具体操作=官方题解1,即DFS暴力匹配,但是逻辑很清楚所以很喜欢。
参考题解:对称美!判断子树 vs 判断相等!

判断两个树是否相等的三个条件是与的关系,即:
1.当前两个树的根节点值相等;
2.并且,s 的左子树和 t 的左子树相等;
3.并且,s 的右子树和 t 的右子树相等。
而判断 t 是否为 s 的子树的三个条件是或的关系,即:
1.当前两棵树相等;
2.或者,t 是 s 的左子树;
3.或者,t 是 s 的右子树。

class Solution:
    def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
        def isSame(node1,node2):
            if not node1 and not node2:
                return True
            if not node1 or not node2:
                return False
            return isSame(node1.left,node2.left) and isSame(node1.right,node2.right) and node1.val==node2.val

        def isSub(node1,node2):
            if not node1 and not node2:
                return True
            if not node1 or not node2:
                return False
            return isSub(node1,node2.left) or isSub(node1,node2.right) or isSame(node1,node2)

        return isSub(t,s)

自己的解法(前序遍历比较结果)

前序遍历对单子树而言,得出的序列是真正的子树序列

具体思路基本上=官方题解2,即DFS序列上的串匹配。不过我不会写KMP……这个算法我就只能脑内跑结果(。以后有空试着写下……

class Solution:
    def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
        def helper(node,r):
            if not node:
                r.append('null')
                return
            r.append(str(node.val))
            helper(node.left,r)
            helper(node.right,r)
        ans1,ans2=[''],['']
        helper(t,ans1)
        helper(s,ans2)
        ans1=' '.join(ans1)
        ans2=' '.join(ans2)
        return True if ans1 in ans2 else False

官方解(树哈希)

参考题解:另一个树的子树

考虑把每个子树都映射成一个唯一的数,如果 t 对应的数字和 s 中任意一个子树映射的数字相等,则 t 是 s 的某一棵子树。

……我有点儿不懂……先马住,慢慢学习(

5.8

题目链接

221. 最大正方形

很喜欢的解法(DP)

参考题解:理解 三者取最小+1

上面详解了 三者取最小 的含义:
图1:受限于左上的0
图2:受限于上边的0
图3:受限于左边的0
数字表示:以此为正方形右下角的最大边长
黄色表示:格子 ? 作为右下角的正方形区域

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        if matrix==[]:
            return 0
        matrix=[[0]*(len(matrix[0])+1)]+[[0]+list(map(int,i)) for i in matrix]
        s=0
        for i in range(1,len(matrix)):
            for j in range(1,len(matrix[0])):
                if matrix[i][j]==1:
                    matrix[i][j]=min(matrix[i-1][j-1],matrix[i-1][j],matrix[i][j-1])+1
                    s=max(s,matrix[i][j])
        return s**2

5.15

题目链接

560. 和为K的子数组

很喜欢的解法(前缀和+哈希表)

参考题解:【熊猫刷题Python3】前缀和+字典,易懂 (附视频题解)

比如我们到某一个位置 i 得到前缀和为 9,也就说从 0 位置到 i 位置的所有数字的和为 9, 如果目标 k 为 3,那么我们只需要找到当前状态下,前面出现了几次 6,就知道以 nums[i] 结尾的和为 3 的连续子数组的个数有多少个。

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        tmp=defaultdict(int)
        tmp[0]=1
        cur_sum = 0
        res = 0
        for i in nums:
            cur_sum += i
            if cur_sum - k in tmp:
                res += tmp[cur_sum - k]
            tmp[cur_sum] += 1
        return res

5.18

题目链接

152. 乘积最大子数组

官方解(DP)

参考题解:乘积最大子数组

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        maxf=nums[0]
        minf=nums[0]
        ans=nums[0]
        for i in range(1,len(nums)):
            tmp1,tmp2=maxf,minf
            maxf=max(tmp1*nums[i],max(nums[i],tmp2*nums[i]))
            minf=min(tmp2*nums[i],min(nums[i],tmp1*nums[i]))
            ans=max(ans,maxf)
        return ans
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355