首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-06-23:合并靠近字符。用go语言,现有仅含小写字母的字符串s与整数k,规则说明如下: 1. 判定标准:同一字符串里,若两个相同字母的

2026-06-23:合并靠近字符。用go语言,现有仅含小写字母的字符串s与整数k,规则说明如下: 1. 判定标准:同一字符串里,若两个相同字母的

作者头像
福大大架构师每日一题
发布2026-06-24 15:57:17
发布2026-06-24 15:57:17
1080
举报

2026-06-23:合并靠近字符。用go语言,现有仅含小写字母的字符串s与整数k,规则说明如下:

  1. 1. 判定标准:同一字符串里,若两个相同字母的位置索引差值不超过k,这两个字符视作相邻靠近字符。
  2. 2. 合并规则:满足靠近条件的一对字符,右边字符直接并入左边字符的位置;合并操作一轮只能处理一组,每完成一次合并就生成新字符串,循环执行直到不存在可合并字符。
  3. 3. 合并优先级(每次操作只选一组合并): ① 优先挑选左侧索引数字最小的那一组可合并字符; ② 若多组字符左侧索引相同,再从中选右侧索引数字最小的一组执行合并。
  4. 4. 输出要求:输出全部合并结束后得到的最终字符串。

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. 1. 优先选左侧索引最小的那一组;
    2. 2. 如果左侧索引相同,则选右侧索引最小的那一组。
  • • 合并的方式是:右侧字符删除,左侧字符保留(相当于右侧合并到左侧)。

注意:合并后字符串长度减 1,后续位置索引会重新计算。


第二步:代码实现思路分析(非代码,只说明逻辑)

提供的 mergeCharacters 函数做的是一次遍历过滤重复字符,不是模拟题目描述的“循环合并”。它的核心逻辑是:

  • • 用一个 last[26] 数组,记录每个字母最近一次被保留在结果中的位置。
  • • 遍历原字符串的每一个字符:
    • • 如果当前字符距离它上一次保留的位置 > k,就保留它,并更新 last
    • • 否则就跳过(合并掉)。

这个逻辑相当于:

  • • 从左到右扫描,只保留那些和前一个同类字符距离超过 k 的字符。
  • • 这实际上执行的是“消除所有靠近字符中的右边那个”,但由于是一次从左到右的贪心,它的结果等价于每次都合并最左侧可合并对中的右侧字符,反复进行直到没有靠近字符。

第三步:对照示例,模拟整个过程

初始字符串:"yybyzybz",k=2,索引从 0 开始:

初始状态:

  • • 索引0: y
  • • 索引1: y → 与索引0距离=1 ≤ 2,符合靠近 → 合并右侧(索引1),保留索引0 得到新串:"ybyzybz"(删除了原索引1的 y)

当前串:"ybyzybz"

索引: 0: y 1: b 2: y 3: z 4: y 5: b 6: z

现在找最近的可合并对:

  • • 看字符 y:索引0 和索引2,距离=2 ≤ 2 → 可合并,右侧为索引2
  • • 字符 y 还有索引2 和索引4,距离=2 ≤ 2 → 也可合并,但是左侧索引2 > 0,所以优先选左侧索引最小的 (0,2) 合并 (0,2),删除索引2的 y 得到新串:"ybzybz"

当前串:"ybzybz"

索引: 0: y 1: b 2: z 3: y 4: b 5: 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完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
)

func mergeCharacters(s string, k int)string {
    last := [26]int{}
    for i := range last {
        last[i] = -k - 1// 保证首次遇到字母 i 时,len(ans)-last[i] > k 是 true
    }

    ans := []byte{}
    for _, ch := range s {
        // ch 在 ans 中的下标是 len(ans)
        iflen(ans)-last[ch-'a'] > k {
            last[ch-'a'] = len(ans)
            ans = append(ans, byte(ch))
        }
    }
    returnstring(ans)
}

func main() {
    s := "yybyzybz"
    k := 2
    result := mergeCharacters(s, k)
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

def merge_characters(s: str, k: int) -> str:
    # 初始化 last 数组,每个字母的上次出现位置,初始值设为 -k-1
    last = [-k - 1] * 26
    ans = []

    for ch in s:
        idx = ord(ch) - ord('a')
        # 如果当前字符与上次出现位置的距离大于 k,则保留
        iflen(ans) - last[idx] > k:
            last[idx] = len(ans)
            ans.append(ch)

    return''.join(ans)


if __name__ == "__main__":
    s = "yybyzybz"
    k = 2
    result = merge_characters(s, k)
    print(result)
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

.

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <vector>

std::string mergeCharacters(const std::string& s, int k) {
    // 初始化 last 数组,每个字母的上次出现位置,初始值设为 -k-1
    std::vector<int> last(26, -k - 1);
    std::string ans;

    for (char ch : s) {
        int idx = ch - 'a';
        // 如果当前字符与上次出现位置的距离大于 k,则保留
        if (static_cast<int>(ans.size()) - last[idx] > k) {
            last[idx] = static_cast<int>(ans.size()); // 记录加入前的索引(即新字符的下标)
            ans.push_back(ch);
        }
    }
    return ans;
}

int main() {
    std::string s = "yybyzybz";
    int k = 2;
    std::string result = mergeCharacters(s, k);
    std::cout << result << std::endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 大体过程详细分解
    • 第一步:理解合并规则
    • 第二步:代码实现思路分析(非代码,只说明逻辑)
    • 第三步:对照示例,模拟整个过程
      • 初始状态:
      • 当前串:"ybyzybz"
      • 当前串:"ybzybz"
    • 第四步:代码逻辑与实际合并过程的关系
  • 复杂度分析
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档