String Manipulation
Master fundamental string operations and character manipulation techniques
Level 1: Foundation - String Manipulation
Basic String Operations
String manipulation involves working with sequences of characters. Understanding basic operations like concatenation, substring extraction, and character access is fundamental to solving string-based problems.
📝 Real-Life Analogy:
Think of strings like sentences in a book. You can read individual letters (characters), combine sentences (concatenation), extract phrases (substrings), or count specific words (character frequency).
TypeScript
// Basic String Operations // 1. String concatenation function concatenateStrings(str1: string, str2: string): string { return str1 + str2; } // 2. Substring extraction function getSubstring(str: string, start: number, end: number): string { return str.substring(start, end); } // 3. Character access function getCharAt(str: string, index: number): string { return str[index] || str.charAt(index); } // 4. String length function getStringLength(str: string): number { return str.length; } // 5. String comparison function compareStrings(str1: string, str2: string): boolean { return str1 === str2; } // 6. Case conversion function toUpperCase(str: string): string { return str.toUpperCase(); } function toLowerCase(str: string): string { return str.toLowerCase(); } // 7. Manual string operations (without built-in methods) function manualConcatenation(str1: string, str2: string): string { let result = ''; for (let i = 0; i < str1.length; i++) { result += str1[i]; } for (let i = 0; i < str2.length; i++) { result += str2[i]; } return result; } // Examples console.log(concatenateStrings("Hello", " World")); // "Hello World" console.log(getSubstring("Programming", 0, 7)); // "Program" console.log(getCharAt("Hello", 1)); // "e" console.log(getStringLength("JavaScript")); // 10
Python
# Basic String Operations # 1. String concatenation def concatenate_strings(str1: str, str2: str) -> str: return str1 + str2 # 2. Substring extraction def get_substring(s: str, start: int, end: int) -> str: return s[start:end] # 3. Character access def get_char_at(s: str, index: int) -> str | None: return s[index] if 0 <= index < len(s) else None # 4. String length def get_string_length(s: str) -> int: return len(s) # 5. String comparison def compare_strings(str1: str, str2: str) -> bool: return str1 == str2 # 6. Case conversion def to_upper_case(s: str) -> str: return s.upper() def to_lower_case(s: str) -> str: return s.lower() # 7. Manual string operations (without built-in methods) def manual_concatenation(str1: str, str2: str) -> str: result = '' for char in str1: result += char for char in str2: result += char return result def manual_substring(s: str, start: int, end: int) -> str: result = '' for i in range(start, min(end, len(s))): result += s[i] return result # Examples print(concatenate_strings("Hello", " World")) # "Hello World" print(get_substring("Programming", 0, 7)) # "Program" print(get_char_at("Hello", 1)) # "e" print(get_string_length("Python")) # 6
OCaml
(* Basic String Operations *) (* 1. String concatenation *) let concatenate_strings str1 str2 = str1 ^ str2 (* 2. Substring extraction *) let get_substring s start len = String.sub s start len (* 3. Character access *) let get_char_at s index = if index >= 0 && index < String.length s then Some s.[index] else None (* 4. String length *) let get_string_length s = String.length s (* 5. String comparison *) let compare_strings str1 str2 = String.equal str1 str2 (* 6. Case conversion *) let to_upper_case s = String.uppercase_ascii s let to_lower_case s = String.lowercase_ascii s (* 7. Manual string operations *) let manual_concatenation str1 str2 = let len1 = String.length str1 in let len2 = String.length str2 in let result = Bytes.create (len1 + len2) in String.blit str1 0 result 0 len1; String.blit str2 0 result len1 len2; Bytes.to_string result let manual_substring s start len = let s_len = String.length s in let actual_len = min len (s_len - start) in if start >= 0 && start < s_len && actual_len > 0 then let result = Bytes.create actual_len in String.blit s start result 0 actual_len; Bytes.to_string result else "" (* Examples *) let example1 = concatenate_strings "Hello" " World";; (* "Hello World" *) let example2 = get_substring "Programming" 0 7;; (* "Program" *) let example3 = get_char_at "Hello" 1;; (* Some 'e' *) let example4 = get_string_length "OCaml";; (* 5 *)
Key String Operations:
- Concatenation: Joining two or more strings together
- Substring: Extracting a portion of a string
- Character Access: Getting individual characters by index
- Length: Determining the number of characters in a string
- Comparison: Checking if two strings are equal
String Traversal and Character Manipulation
String traversal involves iterating through each character in a string to perform operations like counting, searching, or transforming characters.
🚶 Real-Life Analogy:
Think of reading a book page by page, or examining each bead on a necklace one by one. String traversal is like going through each character in sequence to analyze or modify it.
TypeScript
// String Traversal and Character Manipulation // 1. Character frequency counting function countCharacterFrequency(str: string): { [key: string]: number } { const frequency: { [key: string]: number } = {}; for (let i = 0; i < str.length; i++) { const char = str[i]; frequency[char] = (frequency[char] || 0) + 1; } return frequency; } // 2. Find first non-repeating character function findFirstNonRepeating(str: string): string | null { const frequency = countCharacterFrequency(str); for (let i = 0; i < str.length; i++) { if (frequency[str[i]] === 1) { return str[i]; } } return null; } // 3. Remove specific characters function removeCharacter(str: string, charToRemove: string): string { let result = ''; for (let i = 0; i < str.length; i++) { if (str[i] !== charToRemove) { result += str[i]; } } return result; } // 4. Count vowels and consonants function countVowelsAndConsonants(str: string): { vowels: number; consonants: number } { const vowels = 'aeiouAEIOU'; let vowelCount = 0; let consonantCount = 0; for (let i = 0; i < str.length; i++) { const char = str[i]; if (char.match(/[a-zA-Z]/)) { if (vowels.includes(char)) { vowelCount++; } else { consonantCount++; } } } return { vowels: vowelCount, consonants: consonantCount }; } // 5. Replace characters function replaceCharacter(str: string, oldChar: string, newChar: string): string { let result = ''; for (let i = 0; i < str.length; i++) { if (str[i] === oldChar) { result += newChar; } else { result += str[i]; } } return result; } // Examples console.log(countCharacterFrequency("hello")); // {h: 1, e: 1, l: 2, o: 1} console.log(findFirstNonRepeating("abccba")); // null console.log(findFirstNonRepeating("abcdef")); // "a" console.log(removeCharacter("hello world", "l")); // "heo word" console.log(countVowelsAndConsonants("Hello World")); // {vowels: 3, consonants: 7}
Python
# String Traversal and Character Manipulation # 1. Character frequency counting def count_character_frequency(s: str) -> dict[str, int]: frequency = {} for char in s: frequency[char] = frequency.get(char, 0) + 1 return frequency # 2. Find first non-repeating character def find_first_non_repeating(s: str) -> str | None: frequency = count_character_frequency(s) for char in s: if frequency[char] == 1: return char return None # 3. Remove specific characters def remove_character(s: str, char_to_remove: str) -> str: result = '' for char in s: if char != char_to_remove: result += char return result # 4. Count vowels and consonants def count_vowels_and_consonants(s: str) -> dict[str, int]: vowels = 'aeiouAEIOU' vowel_count = 0 consonant_count = 0 for char in s: if char.isalpha(): if char in vowels: vowel_count += 1 else: consonant_count += 1 return {'vowels': vowel_count, 'consonants': consonant_count} # 5. Replace characters def replace_character(s: str, old_char: str, new_char: str) -> str: result = '' for char in s: if char == old_char: result += new_char else: result += char return result # 6. Check if string contains only digits def is_all_digits(s: str) -> bool: for char in s: if not char.isdigit(): return False return True # Examples print(count_character_frequency("hello")) # {'h': 1, 'e': 1, 'l': 2, 'o': 1} print(find_first_non_repeating("abccba")) # None print(find_first_non_repeating("abcdef")) # "a" print(remove_character("hello world", "l")) # "heo word" print(count_vowels_and_consonants("Hello World")) # {'vowels': 3, 'consonants': 7}
OCaml
(* String Traversal and Character Manipulation *) (* 1. Character frequency counting *) let count_character_frequency s = let freq = Hashtbl.create 16 in String.iter (fun char -> let count = try Hashtbl.find freq char with Not_found -> 0 in Hashtbl.replace freq char (count + 1) ) s; freq (* 2. Find first non-repeating character *) let find_first_non_repeating s = let freq = count_character_frequency s in let rec find_first i = if i >= String.length s then None else if Hashtbl.find freq s.[i] = 1 then Some s.[i] else find_first (i + 1) in find_first 0 (* 3. Remove specific characters *) let remove_character s char_to_remove = let buffer = Buffer.create (String.length s) in String.iter (fun char -> if char <> char_to_remove then Buffer.add_char buffer char ) s; Buffer.contents buffer (* 4. Count vowels and consonants *) let count_vowels_and_consonants s = let vowels = "aeiouAEIOU" in let is_vowel c = String.contains vowels c in let is_alpha c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') in let vowel_count = ref 0 in let consonant_count = ref 0 in String.iter (fun char -> if is_alpha char then if is_vowel char then incr vowel_count else incr consonant_count ) s; (!vowel_count, !consonant_count) (* 5. Replace characters *) let replace_character s old_char new_char = let buffer = Buffer.create (String.length s) in String.iter (fun char -> if char = old_char then Buffer.add_char buffer new_char else Buffer.add_char buffer char ) s; Buffer.contents buffer (* 6. Check if string contains only digits *) let is_all_digits s = let rec check i = if i >= String.length s then true else if s.[i] >= '0' && s.[i] <= '9' then check (i + 1) else false in check 0 (* Examples *) let freq_example = count_character_frequency "hello";; let first_non_rep = find_first_non_repeating "abcdef";; (* Some 'a' *) let removed = remove_character "hello world" 'l';; (* "heo word" *) let (vowels, consonants) = count_vowels_and_consonants "Hello World";; (* (3, 7) *)
String Traversal Techniques:
- Linear Traversal: Process each character sequentially
- Frequency Counting: Track occurrences of each character
- Filtering: Remove or replace specific characters
- Classification: Categorize characters (vowels, digits, etc.)
- Pattern Detection: Find specific character patterns
Common String Problems
These are fundamental string manipulation problems that appear frequently in programming interviews and real-world applications.
🧩 Real-Life Analogy:
Think of these problems like word puzzles or games. Reversing a string is like reading a word backwards, checking for palindromes is like finding words that read the same forwards and backwards (like "racecar").
TypeScript
// Common String Problems // 1. Reverse a string (without built-in methods) function reverseString(str: string): string { let result = ''; for (let i = str.length - 1; i >= 0; i--) { result += str[i]; } return result; } // 2. Check if string is palindrome function isPalindrome(str: string): boolean { const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, ''); let left = 0; let right = cleaned.length - 1; while (left < right) { if (cleaned[left] !== cleaned[right]) { return false; } left++; right--; } return true; } // 3. Check if two strings are anagrams function areAnagrams(str1: string, str2: string): boolean { if (str1.length !== str2.length) return false; const freq1 = countCharacterFrequency(str1.toLowerCase()); const freq2 = countCharacterFrequency(str2.toLowerCase()); for (const char in freq1) { if (freq1[char] !== freq2[char]) { return false; } } return true; } // 4. Find longest common prefix function longestCommonPrefix(strings: string[]): string { if (strings.length === 0) return ''; let prefix = ''; const firstString = strings[0]; for (let i = 0; i < firstString.length; i++) { const char = firstString[i]; for (let j = 1; j < strings.length; j++) { if (i >= strings[j].length || strings[j][i] !== char) { return prefix; } } prefix += char; } return prefix; } // 5. Remove duplicates from string function removeDuplicates(str: string): string { const seen = new Set(); let result = ''; for (let i = 0; i < str.length; i++) { const char = str[i]; if (!seen.has(char)) { seen.add(char); result += char; } } return result; } // 6. Check if string is a rotation of another function isRotation(str1: string, str2: string): boolean { if (str1.length !== str2.length) return false; const concatenated = str1 + str1; return concatenated.includes(str2); } // Helper function from previous section function countCharacterFrequency(str: string): { [key: string]: number } { const frequency: { [key: string]: number } = {}; for (let i = 0; i < str.length; i++) { const char = str[i]; frequency[char] = (frequency[char] || 0) + 1; } return frequency; } // Examples console.log(reverseString("hello")); // "olleh" console.log(isPalindrome("A man a plan a canal Panama")); // true console.log(areAnagrams("listen", "silent")); // true console.log(longestCommonPrefix(["flower", "flow", "flight"])); // "fl" console.log(removeDuplicates("programming")); // "progamin" console.log(isRotation("waterbottle", "erbottlewat")); // true
Python
# Common String Problems # 1. Reverse a string (without built-in methods) def reverse_string(s: str) -> str: result = '' for i in range(len(s) - 1, -1, -1): result += s[i] return result # 2. Check if string is palindrome def is_palindrome(s): # Clean the string: remove non-alphanumeric and convert to lowercase cleaned = ''.join(char.lower() for char in s if char.isalnum()) left, right = 0, len(cleaned) - 1 while left < right: if cleaned[left] != cleaned[right]: return False left += 1 right -= 1 return True # 3. Check if two strings are anagrams def are_anagrams(str1, str2): if len(str1) != len(str2): return False freq1 = count_character_frequency(str1.lower()) freq2 = count_character_frequency(str2.lower()) return freq1 == freq2 # 4. Find longest common prefix def longest_common_prefix(strings): if not strings: return '' prefix = '' first_string = strings[0] for i in range(len(first_string)): char = first_string[i] for j in range(1, len(strings)): if i >= len(strings[j]) or strings[j][i] != char: return prefix prefix += char return prefix # 5. Remove duplicates from string def remove_duplicates(s): seen = set() result = '' for char in s: if char not in seen: seen.add(char) result += char return result # 6. Check if string is a rotation of another def is_rotation(str1, str2): if len(str1) != len(str2): return False concatenated = str1 + str1 return str2 in concatenated # 7. Count words in a string def count_words(s): words = s.split() return len(words) # 8. Capitalize first letter of each word def capitalize_words(s): result = '' capitalize_next = True for char in s: if char.isalpha(): if capitalize_next: result += char.upper() capitalize_next = False else: result += char.lower() else: result += char capitalize_next = True return result # Helper function from previous section def count_character_frequency(s): frequency = {} for char in s: frequency[char] = frequency.get(char, 0) + 1 return frequency # Examples print(reverse_string("hello")) # "olleh" print(is_palindrome("A man a plan a canal Panama")) # True print(are_anagrams("listen", "silent")) # True print(longest_common_prefix(["flower", "flow", "flight"])) # "fl" print(remove_duplicates("programming")) # "progamin" print(is_rotation("waterbottle", "erbottlewat")) # True print(capitalize_words("hello world")) # "Hello World"
OCaml
(* Common String Problems *) (* 1. Reverse a string (without built-in methods) *) let reverse_string s = let len = String.length s in let result = Bytes.create len in for i = 0 to len - 1 do Bytes.set result i s.[len - 1 - i] done; Bytes.to_string result (* 2. Check if string is palindrome *) let is_palindrome s = let is_alnum c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') in let to_lower c = if c >= 'A' && c <= 'Z' then char_of_int (int_of_char c + 32) else c in (* Clean the string *) let cleaned = Buffer.create (String.length s) in String.iter (fun c -> if is_alnum c then Buffer.add_char cleaned (to_lower c) ) s; let clean_str = Buffer.contents cleaned in let len = String.length clean_str in let rec check left right = if left >= right then true else if clean_str.[left] <> clean_str.[right] then false else check (left + 1) (right - 1) in check 0 (len - 1) (* 3. Check if two strings are anagrams *) let are_anagrams str1 str2 = if String.length str1 <> String.length str2 then false else let freq1 = count_character_frequency (String.lowercase_ascii str1) in let freq2 = count_character_frequency (String.lowercase_ascii str2) in Hashtbl.fold (fun char count acc -> acc && (try Hashtbl.find freq2 char = count with Not_found -> false) ) freq1 true (* 4. Find longest common prefix *) let longest_common_prefix strings = match strings with | [] -> "" | first :: rest -> let rec find_prefix i = if i >= String.length first then String.sub first 0 i else let char = first.[i] in let rec check_all = function | [] -> find_prefix (i + 1) | s :: ss -> if i >= String.length s || s.[i] <> char then String.sub first 0 i else check_all ss in check_all rest in find_prefix 0 (* 5. Remove duplicates from string *) let remove_duplicates s = let seen = Hashtbl.create 16 in let buffer = Buffer.create (String.length s) in String.iter (fun char -> if not (Hashtbl.mem seen char) then ( Hashtbl.add seen char true; Buffer.add_char buffer char ) ) s; Buffer.contents buffer (* 6. Check if string is a rotation of another *) let is_rotation str1 str2 = if String.length str1 <> String.length str2 then false else let concatenated = str1 ^ str1 in let rec contains_substring s sub start = if start + String.length sub > String.length s then false else if String.sub s start (String.length sub) = sub then true else contains_substring s sub (start + 1) in contains_substring concatenated str2 0 (* Examples *) let reverse_example = reverse_string "hello";; (* "olleh" *) let palindrome_example = is_palindrome "A man a plan a canal Panama";; (* true *) let anagram_example = are_anagrams "listen" "silent";; (* true *) let prefix_example = longest_common_prefix ["flower"; "flow"; "flight"];; (* "fl" *) let duplicates_example = remove_duplicates "programming";; (* "progamin" *) let rotation_example = is_rotation "waterbottle" "erbottlewat";; (* true *)
Common String Problem Patterns:
- Reversal: Process string from end to beginning
- Palindrome: Use two-pointer technique from both ends
- Anagrams: Compare character frequencies
- Prefix/Suffix: Compare characters position by position
- Deduplication: Use hash set to track seen characters
- Rotation: Use string concatenation trick
Problem | Time Complexity | Space Complexity | Key Technique |
---|---|---|---|
Reverse String | O(n) | O(n) | Backward iteration |
Palindrome Check | O(n) | O(1) | Two pointers |
Anagram Check | O(n) | O(k) | Frequency counting |
Common Prefix | O(n×m) | O(1) | Character comparison |
Remove Duplicates | O(n) | O(k) | Hash set tracking |
Ready to practice?
Now that you understand string manipulation fundamentals, let's apply these concepts!
Continue to Practice Focus →