Medium

题目描述

给你一个下标从 0 开始的字符串 s 和一个下标从 0 开始的整数数组 spaces,该数组描述原字符串中需要添加空格的下标位置。每个空格都应该插入到给定下标对应字符的前面。

例如,给定 s = "EnjoyYourCoffee"spaces = [5, 9],我们在下标 5 和 9 对应的字符 ‘Y’ 和 ‘C’ 前面分别放置空格。因此,我们得到 "Enjoy Your Coffee"

返回添加空格后的修改字符串。

示例 1:

输入:s = "LeetcodeHelpsMeLearn", spaces = [8,13,15]
输出:"Leetcode Helps Me Learn"
解释:
下标 8、13 和 15 对应 "LeetcodeHelpsMeLearn" 中带下划线的字符。
然后我们在这些字符前面放置空格。

示例 2:

输入:s = "icodeinpython", spaces = [1,5,7,9]
输出:"i code in py thon"
解释:
下标 1、5、7 和 9 对应 "icodeinpython" 中带下划线的字符。
然后我们在这些字符前面放置空格。

示例 3:

输入:s = "spacing", spaces = [0,1,2,3,4,5,6]
输出:" s p a c i n g"
解释:
我们还可以在字符串的第一个字符前面放置空格。

提示:

  • 1 <= s.length <= 3 * 10^5
  • s 仅包含小写和大写英文字母
  • 1 <= spaces.length <= 3 * 10^5
  • 0 <= spaces[i] <= s.length - 1
  • spaces 中的所有值严格递增

解题思路

解题思路

这道题要求在指定位置插入空格,关键是要理解在某个下标前插入空格的含义。

方法分析:

  1. 暴力方法:遍历字符串,每次遇到需要插入空格的位置就插入,但这样会导致后续位置偏移,需要调整索引,效率较低。

  2. 双指针法(推荐):

    • 使用一个指针 i 遍历原字符串
    • 使用另一个指针 j 跟踪 spaces 数组
    • i 等于 spaces[j] 时,先添加空格,再添加字符,然后移动 j
    • 否则直接添加字符
  3. 预计算长度法:先计算结果字符串的总长度(原长度 + 空格数),然后一次性分配空间填充。

实现要点:

  • 由于 spaces 数组已经排序,我们可以顺序处理
  • 需要注意边界情况,如在字符串开头插入空格
  • 使用 StringBuilder(C#)或类似高效字符串构建方式避免频繁内存分配

时间复杂度为 O(n + m),其中 n 是字符串长度,m 是空格数组长度。空间复杂度为 O(n + m)。

代码实现

class Solution {
public:
    string addSpaces(string s, vector<int>& spaces) {
        string result;
        result.reserve(s.length() + spaces.size()); // 预分配空间
        
        int j = 0; // spaces数组的指针
        for (int i = 0; i < s.length(); i++) {
            // 如果当前位置需要添加空格
            if (j < spaces.size() && i == spaces[j]) {
                result += ' ';
                j++;
            }
            result += s[i];
        }
        
        return result;
    }
};
class Solution:
    def addSpaces(self, s: str, spaces: List[int]) -> str:
        result = []
        j = 0  # spaces数组的指针
        
        for i in range(len(s)):
            # 如果当前位置需要添加空格
            if j < len(spaces) and i == spaces[j]:
                result.append(' ')
                j += 1
            result.append(s[i])
        
        return ''.join(result)
public class Solution {
    public string AddSpaces(string s, int[] spaces) {
        StringBuilder result = new StringBuilder(s.Length + spaces.Length);
        
        int j = 0; // spaces数组的指针
        for (int i = 0; i < s.Length; i++) {
            // 如果当前位置需要添加空格
            if (j < spaces.Length && i == spaces[j]) {
                result.Append(' ');
                j++;
            }
            result.Append(s[i]);
        }
        
        return result.ToString();
    }
}
/**
 * @param {string} s
 * @param {number[]} spaces
 * @return {string}
 */
var addSpaces = function(s, spaces) {
    let result = [];
    let spaceIndex = 0;
    
    for (let i = 0; i < s.length; i++) {
        if (spaceIndex < spaces.length && i === spaces[spaceIndex]) {
            result.push(' ');
            spaceIndex++;
        }
        result.push(s[i]);
    }
    
    return result.join('');
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n + m)n为字符串长度,m为spaces数组长度,需要遍历字符串一次
空间复杂度O(n + m)结果字符串需要额外空间存储原字符串和空格