
2026-06-23合并靠近字符。用go语言现有仅含小写字母的字符串s与整数k规则说明如下判定标准同一字符串里若两个相同字母的位置索引差值不超过k这两个字符视作相邻靠近字符。合并规则满足靠近条件的一对字符右边字符直接并入左边字符的位置合并操作一轮只能处理一组每完成一次合并就生成新字符串循环执行直到不存在可合并字符。合并优先级每次操作只选一组合并① 优先挑选左侧索引数字最小的那一组可合并字符② 若多组字符左侧索引相同再从中选右侧索引数字最小的一组执行合并。输出要求输出全部合并结束后得到的最终字符串。1 s.length 100。1 k s.length。s 由小写英文字母组成。输入 s “yybyzybz”, k 2。输出 “ybzybz”。解释下标 i 0 和 i 1 处的字符 ‘y’ 是靠近的因为 1 - 0 1 k。将它们合并到左侧的 ‘y’得到 s “ybyzybz”。现在下标 i 0 和 i 2 处的字符 ‘y’ 是靠近的因为 2 - 0 2 k。将它们合并到左侧的 ‘y’得到 s “ybzybz”。没有其他相同的字符是靠近的因此不再发生合并。题目来自力扣3853。好的我们先按照题目规则和提供的代码一步步分析这个合并过程的逻辑并对比题目描述来验证。大体过程详细分解第一步理解合并规则相同字符如果在当前字符串中的位置索引差 ≤k就认为它们“靠近”。每次只选一组进行合并优先选左侧索引最小的那一组如果左侧索引相同则选右侧索引最小的那一组。合并的方式是右侧字符删除左侧字符保留相当于右侧合并到左侧。注意合并后字符串长度减 1后续位置索引会重新计算。第二步代码实现思路分析非代码只说明逻辑提供的mergeCharacters函数做的是一次遍历过滤重复字符不是模拟题目描述的“循环合并”。它的核心逻辑是用一个last[26]数组记录每个字母最近一次被保留在结果中的位置。遍历原字符串的每一个字符如果当前字符距离它上一次保留的位置 k就保留它并更新last否则就跳过合并掉。这个逻辑相当于从左到右扫描只保留那些和前一个同类字符距离超过 k的字符。这实际上执行的是“消除所有靠近字符中的右边那个”但由于是一次从左到右的贪心它的结果等价于每次都合并最左侧可合并对中的右侧字符反复进行直到没有靠近字符。第三步对照示例模拟整个过程初始字符串yybyzybzk2索引从 0 开始初始状态索引0: y索引1: y → 与索引0距离1 ≤ 2符合靠近 → 合并右侧索引1保留索引0得到新串ybyzybz删除了原索引1的 y当前串ybyzybz索引0: y1: b2: y3: z4: y5: b6: z现在找最近的可合并对看字符 y索引0 和索引2距离2 ≤ 2 → 可合并右侧为索引2字符 y 还有索引2 和索引4距离2 ≤ 2 → 也可合并但是左侧索引2 0所以优先选左侧索引最小的 (0,2)合并 (0,2)删除索引2的 y得到新串ybzybz当前串ybzybz索引0: y1: b2: z3: y4: b5: z检查所有相同字符对y: 索引0 和索引3距离3 2不靠近其他字符不重复或距离 k因此没有可合并字符结束。最终结果ybzybz与题目输出一致。第四步代码逻辑与实际合并过程的关系代码一次遍历做的其实是上述步骤的压缩版本它保留每个字符第一次出现后只有距离超过 k 的下一个同类字符才会被保留中间的都会被丢弃。这正好等价于反复合并最左可合并对因为每次合并后右侧字符消失左侧字符仍在原位置后续字符左移但代码的“距离k才保留”规则恰恰模拟了这种“删除右侧靠近字符”的操作。复杂度分析时间复杂度遍历一次字符串每个字符只处理一次每次操作是 O(1)数组索引和比较。设 n s.length时间复杂度为O(n)。额外空间复杂度使用了一个长度为 26 的数组记录最后出现位置以及一个字节切片存储结果长度最多 n。因此额外空间是 O(1)常数大小加上结果存储空间输出必须的不计入额外空间时只算辅助空间则为 O(1)。最终答案时间复杂度O(n)额外空间复杂度O(1)不包括输出字符串本身Go完整代码如下packagemainimport(fmt)funcmergeCharacters(sstring,kint)string{last:[26]int{}fori:rangelast{last[i]-k-1// 保证首次遇到字母 i 时len(ans)-last[i] k 是 true}ans:[]byte{}for_,ch:ranges{// ch 在 ans 中的下标是 len(ans)iflen(ans)-last[ch-a]k{last[ch-a]len(ans)ansappend(ans,byte(ch))}}returnstring(ans)}funcmain(){s:yybyzybzk:2result:mergeCharacters(s,k)fmt.Println(result)}Python完整代码如下# -*-coding:utf-8-*-defmerge_characters(s:str,k:int)-str:# 初始化 last 数组每个字母的上次出现位置初始值设为 -k-1last[-k-1]*26ans[]forchins:idxord(ch)-ord(a)# 如果当前字符与上次出现位置的距离大于 k则保留iflen(ans)-last[idx]k:last[idx]len(ans)ans.append(ch)return.join(ans)if__name____main__:syybyzybzk2resultmerge_characters(s,k)print(result)C完整代码如下#includeiostream#includestring#includevectorstd::stringmergeCharacters(conststd::strings,intk){// 初始化 last 数组每个字母的上次出现位置初始值设为 -k-1std::vectorintlast(26,-k-1);std::string ans;for(charch:s){intidxch-a;// 如果当前字符与上次出现位置的距离大于 k则保留if(static_castint(ans.size())-last[idx]k){last[idx]static_castint(ans.size());// 记录加入前的索引即新字符的下标ans.push_back(ch);}}returnans;}intmain(){std::string syybyzybz;intk2;std::string resultmergeCharacters(s,k);std::coutresultstd::endl;return0;}