给你一个由若干 0 和 1 组成的字符串 s ,请你计算并返回将该字符串分割成两个 非空 子字符串(即 左 子字符串和 右 子字符串)所能获得的最大得分。
「分割字符串的得分」为 左 子字符串中 0 的数量加上 右 子字符串中 1 的数量。
尝试着用可以规律化的思维来解题。
对这道题,读题后很容易想到分割的可能性,就是从字符串第一个元素开始,假设s=‘12345’,就会分割为’1’,‘2345’与’12’,‘345’与’123’,‘45’与’1234’,‘5’。
!如果这样的话我就不会像做题时一样忘掉了两个 非空 子字符串这一点了。
所以很容易进一步:通过for循环,每一步都对左右字串进行for循环求分,但这显然不是一个聪明的做法,基于以前刷题的经验,很容易想到,对初始状态左右子串l,r
标识,进行求分,得到结果,之后的for循环对每个元素进行判断,是'0'
则l+1
,是"1"则r-1
.每次都对MAX进行一次判断更新。
class Solution:
def maxScore(self, s: str) -> int:
l,r=s[0].count('0'),s[1:].count('1')
MAX=l+r
for i in s[1:-1]:
if i=='0':l+=1
else:r-=1
MAX=max(MAX,l+r)
return MAX
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
本来毫无思路,差点就要放弃了,在最后才透过这花里胡哨的描述看到本质:
每次都只能选择开头或末尾的卡,最多拿K张牌,求可能的最大点数。
实际上就是不论选择的次序如何,结果就是数组前面的i
个元素和数组后面的k-i
个元素的最大值。求i
,求最大值。
想到这个就很简单了,可以参考5392.
class Solution:
def maxScore(self, cardPoints: List[int], k: int) -> int:
tp=sum(cardPoints[-k:])
MAX=tp
for i in range(k):
tp=tp-cardPoints[-k+i]+cardPoints[i]
MAX=max(MAX,tp)
return MAX
执行用时 :112 ms, 在所有 Python3 提交中击败了100.00%的用户
内存消耗 :24 MB, 在所有 Python3 提交中击败了100.00%的用户
提交早的一个好处就是不管你执行结果是什么鸟样子基本都是双百。
给你一个列表 nums ,里面每一个元素都是一个整数列表。请你依照下面各图的规则,按顺序返回 nums 中对角线上的整数。
第一想法是蠢兮兮的去把不规则数组填满,变成矩形。然后参考24号那天的【力扣】1329:将矩阵按对角线排序 | 数组 | 对角线遍历
里的睿智操作,进行遍历。
class Solution:
def findDiagonalOrder(self, nums):
MAX=0
for i in nums:
MAX=max(MAX,len(i))
for i in range(len(nums)):
nums[i]=nums[i]+[0]*(MAX-len(nums[i]))
res=[]
self.change=(-1,1)
def pack(i, j,MAX):
while 0 <= i < len(nums) and 0 <= j < MAX:
if nums[i][j]:res.append(nums[i][j])
i += self.change[0]
j += self.change[1]
for i in range(len(nums)):
pack(i,0,MAX)
for i in range(1,MAX):
pack(len(nums)-1,i,MAX)
return res
结果就是百分百被长数据打脸。
但是好在那天看到了优秀的思路,对于从左上角到右下角的遍历,因为坐标x=y
,所以相同线上的元素x-y
相同。
很显然,对于这道题,有x+y是一个定值。(我的数学都还给老师了我对不起老师啊)
class Solution:
def findDiagonalOrder(self, nums):
d={}
res=[]
for i in range(len(nums)):
for j in range(len(nums[i])):
if i+j in d:
d[i+j].append(nums[i][j])
else:
d[i+j]=[nums[i][j]]
for i in sorted(d.keys()):
res+=d[i][::-1]
return res
有一个小坑就是一次遍历结束后的值相对题目要求来说是倒序,当然这不是问题,
执行用时 :276 ms, 在所有 Python3 提交中击败了100.00%的用户
内存消耗 :34.6 MB, 在所有 Python3 提交中击败了100.00%的用户
给你一个整数数组 nums
和一个整数 k
,请你返回 非空 子序列元素和的最大值,子序列需要满足:子序列中每两个 相邻 的整数 nums[i] 和 nums[j]
,它们在原数组中的下标 i 和 j 满足 i < j 且 j - i <= k
。
数组的子序列定义为:将数组中的若干个数字删除(可以删除 0 个数字),剩下的数字按照原本的顺序排布。
原数组也可以是子序列。
参加的第十一场周赛了,悲哀就悲哀在于我压轴题总做不出来,爆哭。
想到应该可以用动态规划解决,然而构造动态转移方程时卡住了,想了想还是躺着舒服就不挣扎了。
点击原文
解释:
dp[i]:以下标i为结尾的子序列的和值
M:[i-k,i-1]范围内的dp最大值
转移方程:
if M >= 0:dp[i] = M + nums[i]
else:dp[i] = nums[i]
class Solution:
def constrainedSubsetSum(self, nums, k: int):
dp = [0]*len(nums)
dp[0] = nums[0]
arr = [(nums[0],0)]
for i in range(1,len(nums)):
M = arr[0][0]
if M>=0:dp[i] = M+nums[i]
else:dp[i] = nums[i]
# 这一部分用来维护arr的第一个元素是[i-k,i-1]范围内的dp最大值
while arr and dp[i]>=arr[-1][0]:
arr.pop()
arr.append((dp[i],i))
while arr[0][1]<(i-k+1):
arr.pop(0)
return max(dp)
点击原文
解题思路
每一个新元素的结果取决于前K个结果中的最大值,维护一个滑动窗口,管理前K个结果中的最大值
import collections
class Solution:
def constrainedSubsetSum(self, nums: List[int], k: int) -> int:
n = len(nums)
dp = [0] * n
deque = collections.deque(maxlen=k)
dp[0] = nums[0]
deque.append(0)
for i in range(1, n):
dp[i] = nums[i] + max(0, dp[deque[0]])
if i >= k:
while deque and i - deque[0] >= k:
deque.popleft()
while deque and dp[i] >= dp[deque[-1]]:
deque.pop()
deque.append(i)
#print(dp)
return max(dp)
点击原文
解题思路
定义状态dp[i]为以i结尾的的最大子序和,那么当考虑第i+1个的时候,由于向量两个小标差距不大于k且非空,所以有以下状态转移方程:
d p [ i + 1 ] = m a x ( n u m s [ i + 1 ] , d p [ i + 1 − j ] + d p [ i + 1 ] ) dp[i+1]=max(nums[i+1],dp[i+1-j]+dp[i+1]) dp[i+1]=max(nums[i+1],dp[i+1−j]+dp[i+1]) 1 < = j < = k 1 <=j<=k 1<=j<=k
如果使用蛮力法的话,时间复杂度O(nk)O(nk),会超时。所以需要优化。
由于当前时刻只依赖于前k个时刻的状态,所以快速找到前k个状态中的最大的即可。这个时候联想到滑动窗口最大的题目。
class Solution:
def constrainedSubsetSum(self, nums: List[int], k: int) -> int:
n = len(nums)
dp = nums[:]
dp[0] = nums[0]
res = nums[0]
s = [(nums[0], 0)]
for i in range(1, len(nums)):
dp[i] = max(dp[i], s[0][0] + nums[i])
while s and s[-1][0] <= dp[i]:
s.pop()
s.append((dp[i], i))
if s[0][1] <= i - k:
s.pop(0)
res = max(res, dp[i])
return res