摘要:2025-08-10:变成好标题的最少代价。用go语言,给你一个长度为 n 的字符串 caption。我们把“好标题”定义为:字符串中每个字符都处在某个由至少 3 个相同字母连在一起的区段内(换句话说,字符串被若干长度至少为 3 的相同字母块覆盖)。
2025-08-10:变成好标题的最少代价。用go语言,给你一个长度为 n 的字符串 caption。我们把“好标题”定义为:字符串中每个字符都处在某个由至少 3 个相同字母连在一起的区段内(换句话说,字符串被若干长度至少为 3 的相同字母块覆盖)。
举例说明:
• "aaabbb" 和 "aaaaccc" 属于好标题;
• "aabbb"(前两个 a 只有两个)和 "ccccd"(末尾的 d 独自一位)不是好标题。
你可以对任意位置 i(0 ≤ i
任务是:用最少的这种单步改动次数把原字符串变为一个好标题。如果存在多个在操作次数上同样最优的好标题,选择在字典序上最小的那个作为答案;如果无法变成任何好标题,则返回空字符串 ""。
此外,字典序按常规定义比较:从左到右第一个不同字符处字母较靠前的字符串更小;若一字符串是另一字符串的前缀,则较短的那个更小。
1
caption 只包含小写英文字母。
输入:caption = "cdcd"。
输出:"cccc"。
解释:
无法用少于 2 个操作将字符串变为好标题。2 次操作得到好标题的方案包括:
"dddd" :将 caption[0] 和 caption[2] 变为它们后一个字符 'd' 。
"cccc" :将 caption[1] 和 caption[3] 变为它们前一个字符 'c' 。
由于 "cccc" 字典序比 "dddd" 小,所以返回 "cccc" 。
题目来自力扣3441。
给定函数 minCostGoodCaption 的目标是将输入字符串转换为“好标题”,并最小化操作次数(操作定义为将字符改为其字母表前一个或后一个字母),如果存在多个操作次数相同的最优解,则选择字典序最小的字符串。以下是该函数的详细步骤描述,基于代码逻辑和题目要求。输入示例为 caption = "cdcd",输出为 "cccc"。
• 检查字符串长度 n:
如果 n• 示例:"cdcd" 的长度 n = 4,大于 2,因此继续处理。
• 创建三个数组,用于存储动态规划状态:
f:长度为 n+1 的整数数组。f[i] 表示从字符串位置 i 开始到末尾的子串转换为好标题所需的最小操作次数。初始时:f[n] 被隐式初始化为 0(表示空子串的代价为 0)。f[n-1] 和 f[n-2] 被设置为一个极大值(math.MaxInt/2),因为以位置 n-1 或 n-2 开始的子串长度不足 3,无法形成好标题区段。t:长度为 n+1 的字节数组。t[i] 表示在位置 i 开始的区段所选择的字母(即该区段所有字符将被改为 t[i])。size:长度为 n 的字节数组。size[i] 表示从位置 i 开始的区段的长度(只能是 3、4 或 5)。• 示例:"cdcd" 中 n=4,初始化 f[4]=0(隐式),f[3] 和 f[2] 设置为极大值。
• 从位置 i = n-3 开始向前遍历到 i = 0(即从字符串末尾向前处理)。
• 对于每个位置 i,考虑三种可能的区段长度:k = 3, 4, 5(要求 i+k
• 对每个 k 执行以下步骤:
提取子串并排序:取子串 s[i:i+k],将其字符排序(升序)。排序是为了方便计算最小操作次数。示例(i=0, k=4 时):子串 "cdcd" 排序后为 ['c','c','d','d']。计算操作代价:根据区段长度 k 和排序后的字符,计算将该区段变为全相同字母的最小操作次数:k=3:排序后字符记为 a, b, c(a k=4:排序后字符记为 a, b, c, d。代价为 (c - a) + (d - b)(因为最优策略是将所有字符变为 b 或 c,操作次数相同)。k=5:排序后字符记为 a, b, c, d, e。代价为 (d - a) + (e - b)(因为最优策略是将所有字符变为中位数 c,操作次数为 (c - a) + (c - b) + (d - c) + (e - c) = d + e - a - b)。示例(i=0, k=4):排序后 a='c', b='c', c='d', d='d',代价 (d - c) + (d - c) = 1 + 1 = 2。计算总代价:候选总代价为 cost + f[i+k],其中 f[i+k] 是从位置 i+k 开始到末尾的子串的最小代价(已提前计算,因为处理顺序是倒序)。示例(i=0, k=4):f[4] = 0,总代价为 2 + 0 = 2。创建掩码(mask):在操作代价相同时,掩码用于选择字典序最小的区段序列。掩码是一个 32 位整数,被解释为 4 个字节(从高位到低位:byte3, byte2, byte1, byte0),其构造方式如下:byte3 总是当前区段的字符(即 t[i]),根据 k 选择:k=3 或 k=4:取排序后的中位数(k=3 的 b 或 k=4 的 b)。k=5:取排序后的第三个字符 c。低位字节的设置取决于 k,目的是编码后续字符信息以比较字典序:k=3:byte2, byte1, byte0 都设置为 t[i+3](即下一个区段的字符)。k=4:byte2 设置为当前区段字符(b),byte1, byte0 设置为 t[i+4](即下一个区段的字符)。k=5:byte2, byte1 设置为当前区段字符(c),byte0 设置为 t[i+5](即下一个区段的字符)。掩码比较规则:作为整数比较,较小的掩码对应字典序较小的字符串(因为高位字节影响更大)。示例(i=0, k=4):排序后 b='c',假设 t[4] = 0(初始值),掩码为 int('c')• 选择最佳候选:对于位置 i,比较所有有效 k 的候选(总代价和掩码):
优先选择总代价最小的候选。如果总代价相同,选择掩码最小的候选(以得到字典序最小的字符串)。记录最佳结果到数组:f[i] = best_cost, size[i] = best_k, t[i] = best_character(来自掩码的 byte3)。• 示例("cdcd"):
位置 i=1:只考虑 k=3(因为 i+4=5>4)。子串 "dcd" 排序为 ['c','d','d'],代价 'd' - 'c' = 1,总代价 1 + f[4] = 1。掩码:byte3 = 'd', byte2, byte1, byte0 = t[4] = 0。设置 f[1]=1, size[1]=3, t[1]='d'。位置 i=0:考虑 k=3 和 k=4(k=5 无效)。k=3:子串 "cdc" 排序为 ['c','c','d'],代价 'd' - 'c' = 1,但 f[3] 是极大值,总代价无效。k=4:子串 "cdcd" 排序为 ['c','c','d','d'],代价 2,总代价 2 + f[4] = 2。掩码:byte3 = 'c', byte2 = 'c', byte1, byte0 = t[4]=0。选择此候选。设置 f[0]=2, size[0]=4, t[0]='c'。• 如果 f[0] 为极大值(在代码中未显式检查,但通过初始化隐含),表示无法形成好标题,应返回空字符串。但在处理中,如果 f[0] 有效则继续。
• 使用 t 和 size 数组构建结果字符串:
从位置 i=0 开始。重复以下直到覆盖整个字符串:取 size[i] 个 t[i] 字符,添加到结果缓冲区。更新 i = i + size[i](跳到下一个区段起始位置)。• 示例("cdcd"):i=0, size[0]=4, t[0]='c',添加 "cccc",覆盖整个字符串,返回 "cccc"。
• 在动态规划过程中,掩码确保在操作代价相同时选择字典序最小的区段序列:
掩码的高位字节(byte3)直接对应当前位置的字符,影响字符串的字典序。低位字节编码后续字符信息,使比较更偏向于较早位置的不同字符。• 示例:"cdcd" 有多个 2 次操作的解(如 "dddd"),但 "cccc" 的掩码更小('c'
• 时间复杂度:O(n)。
理由:循环遍历字符串的每个位置(n 次)。每次迭代处理常数个区段长度(3、4、5),每个区段的排序和操作代价计算时间复杂度为 O(1)(因为区段最大长度为 5,排序可视为常数时间)。构建结果字符串也是 O(n)。总体:O(n) * O(1) = O(n)。• 额外空间复杂度:O(n)。
理由:使用了三个数组 f(n+1 长度)、t(n+1 长度)、size(n 长度),每个占用 O(n) 空间。排序子串的临时空间可忽略(最大长度 5)。结果缓冲区占用 O(n)。总体:O(n)。此方法高效地解决了问题,确保最小操作次数和字典序最优性。
.
package mainimport ( "fmt" "math" "slices" "bytes")func minCostGoodCaption(s string)string { n := len(s) if n = 0; i-- { sub := byte(s[i : i+3]) slices.Sort(sub) a, b, c := sub[0], sub[1], sub[2] s3 := int(t[i+3]) res := f[i+3] + int(c-a) mask := int(b)> 24) } ans := make(byte, 0, n) for i := 0; i.
# -*-coding:utf-8-*-from typing import Listdef min_cost_good_caption(s: str) -> str: """ 将输入字符串 s 当作字节流处理(按 s.encode('latin1')), 返回与 Go 版本等价的结果字符串(使用 latin1 解码以保持字节不变)。 """ b = s.encode('latin1') # 以 byte 处理,与 Go 的 byte 行为一致 n = len(b) if n > 24) & 0xFF # 重建答案 ans_bytes = bytearray i = 0 while i我们相信Go语言和算法为普通开发者提供了困境的“面试利器”,并致力于分享全面的编程知识。在这里,您可以找到最新的Go语言教程、算法解析、提升面试竞争力的秘籍以及行业动态。
·
来源:稀鸿市