[英雄星球七月集训LeetCode解题日报] 第8日 前缀和
日报
- 今天的题纠结了半天!
题目
一、 1894. 找到需要补充粉笔的学生编号
1. 题目描述
2. 思路分析
- 设学生一轮总共要s根粉笔,显然k中超过s倍数的数是没用的,我们先把k对s取余:k%=s
- 然后我们求出学生的前缀和,在前缀和里二分找到k落的位置即可。
3. 代码实现
class Solution:
def chalkReplacer(self, chalk: List[int], k: int) -> int:
n = len(chalk)
presum = list(accumulate(chalk))
k %= presum[-1]
return bisect_right(presum,k)%n
二、2256. 最小平均差
链接: 2256. 最小平均差
1. 题目描述
2. 思路分析
- 按题意模拟即可。
- 由于要求连续区间和,因此我们做前缀和优化。
3. 代码实现
class Solution:
def minimumAverageDifference(self, nums: List[int]) -> int:
n = len(nums)
presum = list(accumulate(nums))
ans = 0
min_avg = inf
for i in range(n):
avg = abs(presum[i]//(i+1) - ((presum[n-1]-presum[i])//(n-i-1) if i < n-1 else 0))
if avg < min_avg:
ans = i
min_avg =avg
return ans
三、1737. 满足三条件之一需改变的最少字符数
1. 题目描述
2. 思路分析
- 按题意先计算方案三初始化ans:找两个串中最多的字符,其它字符都变成它。
- 然后分别计算:
- 把a中字符串都变成字符i,b中小于等i的字符都变成i+1以上的字符,消耗的步骤;
- 把b中字符串都变成字符i,a中小于等i的字符都变成i+1以上的字符,消耗的步骤;
- 注意这个i<25,因为如果变成z,另个字符串都变成z+1是不存在的。
3. 代码实现
class Solution:
def minCharacters(self, a: str, b: str) -> int:
m,n = len(a),len(b)
cnt = Counter(a)+Counter(b)
_,c = cnt.most_common(1)[0]
ans = m+n-c
arr1,arr2 = [0]*26,[0]*26
for c in a:
arr1[ord(c)-ord('a')] += 1
for c in b:
arr2[ord(c)-ord('a')] += 1
presum1 = list(accumulate(arr1,initial =0))
presum2 = list(accumulate(arr2,initial =0))
# print(presum1,presum2)
for i in range(26):
if i<25:
ans = min(ans, presum1[26]-presum1[i+1] + presum2[i+1])
ans = min(ans, presum2[26]-presum2[i+1] + presum1[i+1])
return ans
四、2055. 蜡烛之间的盘子
链接: 2055. 蜡烛之间的盘子
1. 题目描述
2. 思路分析
- 预处理把盘子变成1,蜡烛变成0,题目转化为查询区间内被0包围的1的数量,即区间求和。
- 我们可以把每个蜡烛出现的位置整理成有序数组,然后二分的去找每个查询区间内最左边和最右边的蜡烛。
- 也可以对每个位置预处理一个它左边、右边最近的蜡烛位置。
- 这样对于每个查询[l,r],我们先计算这个查询l右边第一个蜡烛位置left,r左边第一蜡烛位置right,那么[left,right]内的盘子数量就是答案。
- 由于是区间求和,用前缀和优化即可
3. 代码实现
class Solution:
def platesBetweenCandles(self, s: str, queries: List[List[int]]) -> List[int]:
n = len(s)
left,right = [n]*n, [n]*n
l = -1
for i in range(n):
if s[i] == '|':
l = i
left[i] = l
r = n
for i in range(n-1,-1,-1):
if s[i] == '|':
r = i
right[i] = r
dish = list(accumulate([1 if c == '*' else 0 for c in s], initial=0))
ans = []
for l,r in queries:
first = right[l]
last = left[r]
# print(first,last)
if first >= last :
ans.append(0)
else:
ans.append(dish[last+1] - dish[first])
return ans