获得徽章 20
- #刷题交流# 第21天:小D的`abc`变换问题
解题思路:
首先,定义一个函数 changeLetter,它的作用是根据给定的字符进行对应的变换。具体来说,就是通过判断传入的字符是‘a’、‘b’还是‘c’,然后分别返回对应的变换后的字符串,比如传入‘a’就返回‘bc’,传入‘b’返回‘ca’,传入‘c’返回‘ab’。
定义另一个函数 changeLetterList。它接收原始字符串 s 和操作次数 k 作为参数。在函数内部,通过一个循环来重复进行操作,循环次数就是给定的 k 值。每次循环时,会利用生成器表达式和 join 函数,将原字符串中的每个字符都经过 changeLetter 函数进行变换,然后把变换后的结果拼接起来,得到新的字符串,并且将新字符串赋值给原字符串变量,以便下一次循环继续基于新的状态进行变换。
核心代码:
def changeLetter(alpha):
if alpha == 'a':
alpha = 'bc'
elif alpha == 'b':
alpha = 'ca'
elif alpha == 'c':
alpha ='ab'
return alpha
def changeLetterList(s,k):
new_s = ''
for _ in range(k):
new_s = ''.join(changeLetter(ch) for ch in s)
s = new_s
return new_s
21天,21天,加油⛽️!!!展开评论1 - #刷题交流# 第20天:股票市场交易策略优化
为了帮助小R计算出在遵守交易规则的情况下能够获得的最大利润,我们可以使用动态规划(Dynamic Programming, DP)的方法来解决问题。我们定义三个状态:
● hold:表示持有股票时的最大收益。
● sell:表示卖出股票后的最大收益。
● rest:表示处于冷冻期或选择休息(不买卖)时的最大收益。
这三个状态之间的转移方程如下:
● hold[i] = max(hold[i - 1], rest[i - 1] - price[i]):要么保持之前的持有状态,要么从冷冻期后购买新股票。
● sell[i] = hold[i - 1] + price[i]:只能从前一天的持有状态转变而来,表示今天卖出股票。
● rest[i] = max(rest[i - 1], sell[i - 1]):要么从前一天的冷冻期或卖出状态转变而来,表示今天不进行任何操作。
初始条件为:
● hold[0] = -price[0]:第一天买入股票后的收益。
● sell[0] = 0:第一天没有可以卖出的股票。
● rest[0] = 0:第一天没有之前的操作,所以休息的收益为0。
最后的结果是最后一天的 sell 和 rest 状态中的较大值,因为如果最后一天持有股票则不是最优解(除非最后一日的股价为负,但这是题目所不允许的情况)。
核心代码:
# 初始化状态
hold, sell, rest = -stocks[0], 0, 0
for i in range(1, len(stocks)):
# 必须先保存旧的 hold 值,因为它会被新的 hold 值覆盖,而 sell 需要使用旧的 hold 值
old_hold = hold
hold = max(hold, rest - stocks[i])
rest = max(rest, sell)
sell = old_hold + stocks[i]
# 返回最后一天 sell 或 rest 状态中的较大值
return max(sell, rest)
20天了,加油⛽️ 不积跬步,无以至千里;不积小流,无以成江海。展开46 - #刷题交流# 第19天:最少前缀操作问题
暴力枚举前缀长度:
○ 我们首先考虑 T 的所有可能前缀,从长度为 0 到 min(len(S), len(T))。对于每个可能的前缀长度 i,我们取出 S 的前 i 个字符组成 cur_s。
○ 计算将 S 变为长度为 i 的 T 的前缀所需的操作次数。操作次数初始化为将 S 截断到长度 i 所需删除末尾字符的次数,即 len(S) - i。
○ 然后,我们逐个比较 cur_s 和 T 的前 i 个字符,如果字符不相同,则需要一次修改操作,将操作次数加 1。
○ 最后,我们更新全局的最少操作次数 min_op。
核心代码:
# 枚举T的可能前缀长度
for i in range(min(m, n) + 1):
cur_s = S[:i]
op_count = len(S) - i
# 计算当前前缀下的操作次数
for j in range(len(cur_s)):
if cur_s[j]!= T[j]:
op_count += 1
# 更新最少操作次数
min_op = min(min_op, op_count)
加油⛽️加油,19天了。
展开评论2 - #刷题交流# 第15天:比赛配对问题
这个问题本质上是要模拟一个淘汰赛的过程,直到剩下唯一的一支获胜队伍。在每一轮中,根据队伍数的奇偶性进行配对,直到队伍数降到 1 为止。我们需要统计总共进行的比赛次数。
思路
1. 奇偶性判断:
○ 如果队伍数是偶数,则每两支队伍配对,进行n/2场比赛,剩下的队伍数也会减少为n/2。
○ 如果队伍数是奇数,则有一支队伍轮空,其他队伍配对,进行(n-1)/2场比赛,剩下的队伍数会变为 (n-1)/2 + 1(即(n+1)/2)。
2. 比赛次数累计:
○ 每进行一轮比赛时,都需要根据当前队伍数判断进行多少场比赛,并更新剩下的队伍数,直到剩下的队伍数为 1。
3. 结束条件:
○ 当队伍数剩下 1 时,比赛结束。
核心代码:
while n > 1:
if n % 2 == 0:
# 如果队伍数是偶数,每两支队伍配对
matches += n // 2
n //= 2
else:
# 如果队伍数是奇数,轮空一支队伍,其他队伍配对
matches += (n - 1) // 2
n = (n - 1) // 2 + 1
加油,15天,已经过半了!!展开评论1 - #刷题交流# 第14天:小B的极差之和
问题分析:
我们需要求出数组 b 的所有连续子数组的极差之和,极差定义为子数组中的最大值减去最小值。
给定数组 a,它描述了如何构造数组 b,数组 b 中有 a[i] 个 i+1。例如,如果 a = [2, 3, 1],那么数组 b 将是 [1, 1, 2, 2, 2, 3]。
目标:
1. 构造数组 b。
2. 计算所有连续子数组的极差之和。
由于构造数组 b 可能非常大(最大可能的长度为 sum(a)),直接遍历所有子数组并计算其极差是不现实的。我们需要通过一种优化的方法来处理这个问题。
解决方案
1. 构造数组 b:直接根据数组 a 构造数组 b,每个元素 i+1 出现 a[i] 次。
2. 计算极差:我们需要考虑如何快速计算数组 b 中所有子数组的极差之和。
○ 对于每个元素 x,我们需要知道它作为子数组最大值或最小值的贡献。
○ 假设元素 x 在某些子数组中是最大值或最小值,那么我们需要计算这个元素作为最大值或最小值的子数组的数量。
3. 优化计算:可以通过单调栈来计算每个元素作为最大值和最小值出现的次数,进而计算其对极差的贡献。展开评论2 - #刷题交流# 第一天:创意标题匹配问题
解题思路
1. 模板转换为正则表达式
● 目标:将含有通配符的模板转换成一个正则表达式,以便后续的匹配操作。
● 步骤:
a. 转义特殊字符:模板中可能包含正则表达式中的特殊字符(如 ., *, ?, {, }, [, ] 等)进行转义,通过函数escape实现。
b. 替换通配符:将模板中的每个通配符 {...} 替换为正则表达式的 .*?,表示它可以匹配任意长度的任意字符(非贪婪匹配)。通过函数sub实现。
2. 匹配标题
● 目标:使用生成的正则表达式来匹配每个给定的标题,判断其是否符合模板。
● 步骤:
a. 编译正则表达式:使用 re.compile 编译生成的正则表达式。
b. 全匹配:使用 re.fullmatch 方法来检查每个标题是否完全符合正则表达式。
c. 记录结果:将每个标题的匹配结果(True 或 False)记录下来。
3. 返回结果
● 目标:将所有标题的匹配结果以逗号分隔的字符串形式返回。
● 步骤:
a. 拼接结果:将所有匹配结果(True 或 False)拼接成一个逗号分隔的字符串。
b. 返回结果:返回拼接好的字符串。展开评论2