String Transformation Algorithms: Reversal, Rotation, and Space Manipulation Techniques
- In-Place String Reversal
The problem requires reversing a character array without allocating additional memory, achieving O(1) space complexity. While most languages provide built-in reversal functions, implementing the algorithm manually demonstrates fundamental pointer manipulation skills.
The optimal approach employs a two-pointer technique. Place one pointer at the beginning and another at the end of the array, then progressively swap elements while moving the pointers toward the center.
void reverseString(std::vector<char>& chars) {
int start = 0;
int end = chars.size() - 1;
while (start < end) {
// Manual swap without using library function
char temp = chars[start];
chars[start] = chars[end];
chars[end] = temp;
start++;
end--;
}
}
Alternative swap implementations include bitwise XOR operations or std::exchange, though the three-line manual swap offers the best clarity.
- Selective Segment Reversal
This variation adds complexity by requiring reversal of only the first k characters in every 2k segment. The key insight involves jumping through the string in 2k increments rather than processing each character sequentially.
std::string reverseSegments(std::string str, int k) {
size_t pos = 0;
while (pos < str.length()) {
// Check if we have at least k characters remaining
if (pos + k <= str.length()) {
// Reverse first k characters in current segment
size_t left = pos;
size_t right = pos + k - 1;
while (left < right) {
std::swap(str[left++], str[right--]);
}
} else {
// Reverse all remaining characters
size_t left = pos;
size_t right = str.length() - 1;
while (left < right) {
std::swap(str[left++], str[right--]);
}
}
pos += 2 * k;
}
return str;
}
The algorithm efficiently processes the string by skipping fully processed segments, avoiding unnecessary boundary checks within each iteration.
- Space Replacement with Percent Encoding
Trensform each space character into "%20" without using extra storage. The solution involves pre-calculating the final length and performing backward population to prevent repeated shifting.
std::string encodeSpaces(std::string& text) {
size_t spaceCount = 0;
size_t originalLen = text.length();
// Count spaces to determine expanded size
for (char c : text) {
if (c == ' ') spaceCount++;
}
// Resize string to accommodate "%20" for each space
text.resize(originalLen + spaceCount * 2);
size_t writePos = text.length() - 1;
size_t readPos = originalLen - 1;
// Backward writing prevents O(n²) shifting
while (readPos < writePos) {
if (text[readPos] == ' ') {
text[writePos--] = '0';
text[writePos--] = '2';
text[writePos--] = '%';
} else {
text[writePos--] = text[readPos];
}
readPos--;
}
return text;
}
This technique ensures each character moves at most once, achieving O(n) time complexity with constant extra space.
- Word Order Reversal
Reverse the order of words while maintaining their original characters and normalizing spacing. The strategy involves three phases: space normalization, complete string reversal, and individual word correction.
void trimAndNormalize(std::string& s) {
size_t writeIdx = 0;
bool firstWord = true;
for (size_t readIdx = 0; readIdx < s.length(); ++readIdx) {
if (s[readIdx] != ' ') {
// Add single space before subsequent words
if (!firstWord) {
s[writeIdx++] = ' ';
}
// Copy entire word
while (readIdx < s.length() && s[readIdx] != ' ') {
s[writeIdx++] = s[readIdx++];
}
firstWord = false;
}
}
s.resize(writeIdx);
}
void reverseRange(std::string& s, size_t left, size_t right) {
while (left < right) {
std::swap(s[left++], s[right--]);
}
}
std::string reverseWordOrder(std::string s) {
// Phase 1: Remove extra spaces
trimAndNormalize(s);
// Phase 2: Reverse entire string
reverseRange(s, 0, s.length() - 1);
// Phase 3: Reverse each word individually
size_t wordStart = 0;
for (size_t i = 0; i <= s.length(); ++i) {
if (i == s.length() || s[i] == ' ') {
reverseRange(s, wordStart, i - 1);
wordStart = i + 1;
}
}
return s;
}
The normalization step uses a single pass with read/write pointers, eliminating O(n²) erase operations.
- Left Rotation via Reversals
Rotate a string left by n positions using only in-place operations. The clever solution applies targeted reversals: first on the prefix, then the suffix, and finally the entire string.
void reverseSubstring(std::string& s, size_t begin, size_t finish) {
while (begin < finish) {
std::swap(s[begin++], s[finish--]);
}
}
std::string leftRotate(std::string s, size_t n) {
if (s.empty() || n >= s.length()) return s;
// Three-step reversal process
reverseSubstring(s, 0, n - 1); // Reverse prefix
reverseSubstring(s, n, s.length() - 1); // Reverse suffix
reverseSubstring(s, 0, s.length() - 1); // Reverse entire string
return s;
}
This approach achieves the rotation in O(n) time with O(1) auxiliary space, demonstrating how composition of simple operations can solve complex problems efficiently.