a替换函数| 豆包MarsCode AI 刷题

132 阅读5分钟

问题描述

给定一个字符串ss,编写一个函数,将字符串中的小写字母a替换为"%100",并返回替换后的字符串。 例如,对于字符串"abcdwa",所有a字符会被替换为"%100",最终结果为%100bcdw%100"

题目分析

这个题目比较简单,把字符串中的a字符会被替换为"%100",很直接的想法就是遍历原来的字符串,找到a字符存在的位置,然后利用字符串拼接的方法把a字符进行替换。主要可以总结为如下4个步骤:

  1. 初始化结果字符串:创建一个新的字符串来存储替换后的结果。
  2. 遍历输入字符串:逐个字符检查输入字符串,注意这里的输入字符串需要是原来最初的字符串。
  3. 替换字符:如果当前字符是 'a',则用 "%100" 替换,我的实现思路是将字符 'a'之前的字符和 "%100" 以及字符 'a'之后的字符拼接作为新的字符串, 注意在拼接时,结果字符串的长度会发生变化,因此在下一次出现字符 'a'再次进行拼接的时候需要动态调整索引。这里我引入了一个 'count'变量来记录进行替换的次数。
  4. 返回结果字符串:完成遍历后,返回结果字符串。

代码实现

#include <string>

std::string solution(const std::string &s) {
  std::string s_new = s;
  int count = 0;
  for (int i = 0; i < s.size(); ++i) {
    if (s[i] == 'a') {
      s_new = s_new.substr(0, i + count * 3) + "%100" +
              s_new.substr(i + (count * 3) + 1);
      count += 1;
    }
  }
  return s_new;
}

int main() {
  std::cout << (solution("abcdwa") == "%100bcdw%100") << std::endl;
  std::cout << (solution("banana") == "b%100n%100n%100") << std::endl;
  std::cout << (solution("apple") == "%100pple") << std::endl;

  return 0;
}

代码讲解

  • if语句判断当前遍历字符是否为'a'
  • 如果是'a',执行替换操作:
    1. s_new.substr(0, i + count * 3):提取'a'之前的子字符串。
    2. "%100":用"%100"替换'a'
    3. s_new.substr(i + (count * 3) + 1):提取'a'之后的子字符串。
  • 替换后的字符串重新赋值给s_new
  • 注意,count变量记录替换的次数,因为每次替换后,字符串长度会增加3("%100"替换'a')。

性能与优化

尽管上述代码功能正确,但对于大规模字符串处理可能存在性能瓶颈。

使用流式处理: 替代每次替换后重新创建字符串的做法,可以用一个字符串流逐步拼接结果,这样可以避免频繁的字符串复制操作。

#include <string>

std::string solution(const std::string &s) {
  std::string result; // 用于存储替换后的结果字符串

  // 遍历输入字符串
  for (char c : s) {
    if (c == 'a') {
      // 如果当前字符是 'a',则追加 "%100" 到结果字符串
      result.append("%100");
    } else {
      // 否则,追加当前字符到结果字符串
      result.push_back(c);
    }
  }

  return result; // 返回替换后的结果字符串
}

int main() {
  std::cout << (solution("abcdwa") == "%100bcdw%100") << std::endl;
  std::cout << (solution("banana") == "b%100n%100n%100") << std::endl;
  std::cout << (solution("apple") == "%100pple") << std::endl;

  return 0;
}

代码对比

相对于第一段的代码,第二段代码有以下显著的改进和优势

1. 提高了代码的效率

  • 原代码的问题

    • 原代码每次替换'a'时都会使用substr对字符串进行切割和拼接,这导致了额外的内存分配和字符串复制操作,增加了时间和空间复杂度。
    • 每次调用substr需要创建新的字符串对象,频繁的创建、销毁和拼接字符串对性能非常不利,尤其是当字符串长度较大或替换频率较高时。
  • 改进代码的优势

    • 改进后的代码采用了一个独立的结果字符串result,通过appendpush_back方法直接构建替换后的字符串。appendpush_back操作效率更高,因为它们直接在result后追加数据,无需反复创建和销毁临时对象。

2. 代码简洁,逻辑清晰

  • 原代码的复杂性

    • 原代码使用了较为复杂的逻辑来动态调整字符串索引(count * 3)以处理替换后字符串长度的变化,这使得代码在逻辑上显得臃肿,维护性较差。
    • 对于需要频繁替换的场景,这种复杂的索引调整会让代码显得难以阅读和理解。
  • 改进代码的简洁性

    • 改进后的代码通过for (char c : s)直接遍历每个字符,并简单判断是否是'a',逻辑清晰明了,无需考虑替换后字符串长度的动态变化。
    • 整体代码更易读、易维护。

3. 内存管理更高效

  • 原代码的内存问题

    • 原代码每次替换时都会生成新的字符串对象(通过substr),这导致了频繁的内存分配和释放操作。
    • 对于长字符串,内存消耗会显著增加,甚至可能导致内存碎片化。
  • 改进代码的内存优势

    • 改进后的代码只使用一个结果字符串result,减少了不必要的临时对象创建。
    • appendpush_back在大多数实现中都有优化,能够有效利用内存,无需频繁分配和销毁。