You are given a 0-indexed string s
and a 0-indexed integer array spaces
that describes the indices in the original string where spaces will be added. Each space should be inserted before the character at the given index.
s = "EnjoyYourCoffee"
and spaces = [5, 9]
, we place spaces before 'Y'
and 'C'
, which are at indices 5
and 9
respectively. Thus, we obtain "Enjoy Your Coffee"
.Return the modified string after the spaces have been added.
Example 1:
Input: s = "LeetcodeHelpsMeLearn", spaces = [8,13,15] Output: "Leetcode Helps Me Learn" Explanation: The indices 8, 13, and 15 correspond to the underlined characters in "LeetcodeHelpsMeLearn". We then place spaces before those characters.
Example 2:
Input: s = "icodeinpython", spaces = [1,5,7,9] Output: "i code in py thon" Explanation: The indices 1, 5, 7, and 9 correspond to the underlined characters in "icodeinpython". We then place spaces before those characters.
Example 3:
Input: s = "spacing", spaces = [0,1,2,3,4,5,6] Output: " s p a c i n g" Explanation: We are also able to place spaces before the first character of the string.
Constraints:
1 <= s.length <= 3 * 105
s
consists only of lowercase and uppercase English letters.1 <= spaces.length <= 3 * 105
0 <= spaces[i] <= s.length - 1
spaces
are strictly increasing.This problem involves inserting spaces into a string at specific indices provided in an integer array. The solution employs a two-pointer approach for efficient string manipulation.
Approach:
We use two pointers:
i
: Iterates through the input string s
.j
: Iterates through the spaces
array, indicating where spaces should be added.The algorithm proceeds as follows:
Initialization: Initialize an empty string or array ans
to store the result. Set i
and j
to 0.
Iteration: Iterate through the input string s
using pointer i
.
Space Check: At each index i
, check if it matches an index in the spaces
array using pointer j
. If i == spaces[j]
, it means a space should be added before the character at index i
. Add a space to ans
, and increment j
to move to the next space index.
Character Append: Regardless of whether a space was added, append the character s[i]
to ans
. Increment i
to move to the next character.
Termination: Continue this process until the entire string s
has been processed (i
reaches the end of s
).
Return: Finally, convert ans
(which might be an array of characters) into a string and return it.
Time Complexity Analysis:
The algorithm iterates through the string s
once and the spaces
array at most once. Therefore, the time complexity is O(m + n), where n
is the length of the string s
and m
is the length of the spaces
array. This is a linear time complexity.
Space Complexity Analysis:
The space complexity depends on the method used to build the resulting string. If we use an array to accumulate characters and then join them into a string, the space complexity becomes O(m + n) in the worst case (when all indices in spaces
require spaces to be added). In-place modification isn't possible here because we're inserting new characters into the string, so extra space is required. If a string builder is used (as in Java's StringBuilder
), the space complexity remains O(m + n) but might be slightly better in practice due to efficient memory management.
Code Examples (with slight variations based on language):
Python:
class Solution:
def addSpaces(self, s: str, spaces: List[int]) -> str:
result = []
space_index = 0
for i, char in enumerate(s):
if space_index < len(spaces) and i == spaces[space_index]:
result.append(" ")
space_index += 1
result.append(char)
return "".join(result)
Java:
class Solution {
public String addSpaces(String s, int[] spaces) {
StringBuilder sb = new StringBuilder();
int spaceIndex = 0;
for (int i = 0; i < s.length(); i++) {
if (spaceIndex < spaces.length && i == spaces[spaceIndex]) {
sb.append(" ");
spaceIndex++;
}
sb.append(s.charAt(i));
}
return sb.toString();
}
}
C++:
string addSpaces(string s, vector<int>& spaces) {
string result = "";
int spaceIndex = 0;
for (int i = 0; i < s.length(); i++) {
if (spaceIndex < spaces.size() && i == spaces[spaceIndex]) {
result += " ";
spaceIndex++;
}
result += s[i];
}
return result;
}
JavaScript:
const addSpaces = (s, spaces) => {
let result = "";
let spaceIndex = 0;
for (let i = 0; i < s.length; i++) {
if (spaceIndex < spaces.length && i === spaces[spaceIndex]) {
result += " ";
spaceIndex++;
}
result += s[i];
}
return result;
};
These examples all demonstrate the core two-pointer approach. The choice of using a list/array or a string builder is primarily a stylistic choice in most languages, though StringBuilder
in Java and similar constructs in other languages offer better performance for large string manipulations.