String Manipulation
Master the fundamental string operations that appear in nearly every coding problem: traversal, slicing, searching, and transformation.
Learn & Reference
Understanding the Pattern
String Manipulation
Strings are one of the most common data types in programming. Nearly every coding problem involves strings in some way, whether as input, output, or intermediate processing. Mastering basic string operations builds the foundation for more advanced patterns like two pointers, sliding window, and dynamic programming.
Core Operations
Traversal
Iterate through characters one at a time. Most string problems start here — process each character and build a result.
Slicing & Substrings
Extract portions of a string by index range. Essential for problems involving words, prefixes, and suffixes.
Searching
Find characters or substrings within a string. Know your language's built-in search methods to avoid writing manual loops.
Transformation
Convert between cases, replace characters, split/join, and reverse. These operations compose together to solve most string problems.
Key Principles
- Strings are immutable in most languages — build new strings instead of modifying in place (except Go byte slices and Java char arrays)
- Use built-in methods first —
split,join,replace,trimare optimized and less error-prone than manual loops - Watch for off-by-one errors — string indices are 0-based, and slicing end indices are exclusive
- Consider character encoding — ASCII vs Unicode matters for problems involving char codes or special characters
Common Problem Patterns
- Character counting — frequency maps, finding unique/repeated characters
- String building — construct output character by character
- Two-pass approach — first pass gathers info, second pass builds result
- In-place simulation — work with character arrays when mutation is needed
Common Mistakes
- Forgetting strings are immutable: Concatenating in a loop creates O(n²) time in many languages — use string builder or join
- Off-by-one in slicing:
s[0:3]gives 3 characters (indices 0, 1, 2), not 4 - Not handling empty strings: Always check for empty input before processing
- Case sensitivity: Forgetting to normalize case when comparing characters
- Whitespace handling: Not trimming input or handling multiple consecutive spaces
When to Use
Template
1# --- Iterate Characters ---2for ch in s:3# process each character45# --- Build String from Characters ---6result = []7for ch in s:8result.append(ch.upper())9result_str = ''.join(result)1011# --- Process Words ---12words = s.split()13processed = [word.strip() for word in words]14result = ' '.join(processed)1516# --- Character-by-Character Transform ---17def transform(s):18return ''.join(19ch.upper() if ch.isalpha() else ch20for ch in s21)
Syntax Reference
1# === String Basics ===2s = "hello"3len(s) # length: 54s[0] # access: 'h'5s[-1] # last char: 'o'6s[1:4] # slice: 'ell'7s[::-1] # reverse: 'olleh'89# === Search & Check ===10s.find('ll') # index of substring: 2 (-1 if not found)11s.index('ll') # same but raises ValueError12'ell' in s # contains: True13s.startswith('he') # True14s.endswith('lo') # True15s.count('l') # occurrences: 21617# === Transform ===18s.upper() # 'HELLO'19s.lower() # 'hello'20s.capitalize() # 'Hello'21s.title() # 'Hello' (each word)22s.strip() # trim whitespace23s.replace('l', 'r') # 'herro'24s.split(' ') # split into list25' '.join(['a', 'b']) # join: 'a b'2627# === Character Checks ===28ch.isalpha() # letter?29ch.isdigit() # digit?30ch.isalnum() # letter or digit?31ch.isspace() # whitespace?32ord('a') # char code: 9733chr(97) # code to char: 'a'
Common Recipes
1# --- Reverse a String ---2def reverse_string(s):3return s[::-1]45# --- Count Character Frequency ---6from collections import Counter7def char_frequency(s):8return dict(Counter(s))910# --- Check Palindrome ---11def is_palindrome(s):12return s == s[::-1]1314# --- Capitalize Each Word ---15def capitalize_words(s):16return ' '.join(word.capitalize() for word in s.split())1718# --- Remove Duplicate Characters (preserve order) ---19def remove_duplicates(s):20seen = set()21result = []22for ch in s:23if ch not in seen:24seen.add(ch)25result.append(ch)26return ''.join(result)
Complexity
| Operation | Time | Notes |
|---|---|---|
| Access char by index | O(1) | Direct index access |
| Concatenation | O(n) | Creates new string (immutable) |
| Slice / Substring | O(k) | k = length of slice |
| Search (find/indexOf) | O(n*m) | n = string, m = pattern |
| Split / Join | O(n) | Processes entire string |
| Reverse | O(n) | Must copy all characters |
| Replace all | O(n) | Scans entire string |
Watch Out
- ✗Forgetting strings are immutable: Concatenating in a loop creates O(n²) time in many languages — use string builder or join
- ✗Off-by-one in slicing: `s[0:3]` gives 3 characters (indices 0, 1, 2), not 4
- ✗Not handling empty strings: Always check for empty input before processing
- ✗Case sensitivity: Forgetting to normalize case when comparing characters
- ✗Whitespace handling: Not trimming input or handling multiple consecutive spaces