Strings 路 String Fundamentals

String Manipulation Basics

Character-frequency comparison between strings.

  • 5 min read
  • 7 practice questions
  • 3 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: expand around the center
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Strings look like arrays of letters, but they differ in three ways that matter. They can't be changed in place. A Java char isn't always a whole character. And many string questions ("same letters?", "reads the same backwards?") are about counts and symmetry rather than positions. This skill covers the standard techniques, counting and two-pointer or center expansion, and the standard ways each one goes wrong on real text.

We'll go from simple to more technical:

  1. The pattern: count characters (anagrams), and compare from both ends (palindromes).
  2. A second flavor: expand around every center to find the longest palindrome.
  3. Where these show up in production (search, deduplication, validation).
  4. What breaks it: assumed alphabets, Unicode, building strings in loops, ==.

The approach

Java

boolean isAnagram(String s, String t) {
    if (s.length() != t.length()) return false;      // different lengths can never match
    int[] counts = new int[26];                      // lowercase a-z only
    for (int i = 0; i < s.length(); i++) {
        counts[s.charAt(i) - 'a']++;
        counts[t.charAt(i) - 'a']--;
    }
    for (int c : counts) if (c != 0) return false;
    return true;
}

Python

def is_anagram(s: str, t: str) -> bool:
    if len(s) != len(t):
        return False                                 # different lengths can never match
    counts = [0] * 26                                # lowercase a-z only
    for a, b in zip(s, t):
        counts[ord(a) - ord("a")] += 1
        counts[ord(b) - ord("a")] -= 1
    return all(c == 0 for c in counts)

# for any alphabet: collections.Counter(s) == collections.Counter(t)

Two strings are anagrams exactly when every character appears the same number of times in both, so count instead of sorting: O(n) rather than O(n log n), with a 26-slot array in place of a HashMap. The index c - 'a' is the assumption to watch: 'A' - 'a' is -32, so an uppercase letter throws ArrayIndexOutOfBoundsException. For ASCII input use new int[128] indexed by the char itself; for arbitrary Unicode, count code points (s.codePoints()) in a map - counting chars in a HashMap<Character, Integer> counts the two halves of an emoji separately, and "馃敟馃" and "馃敄馃ぅ" then look like anagrams.

A second flavor: expand around the center

Palindromes are about symmetry. To check one string, move two pointers inward from the ends. To find the longest palindromic substring, grow outward from every possible center:

Java

int longestPalindromeLength(String s) {
    int best = 0;
    for (int c = 0; c < s.length(); c++) {
        best = Math.max(best, expand(s, c, c));      // odd length: centered on a character
        best = Math.max(best, expand(s, c, c + 1));  // even length: centered on a gap
    }
    return best;
}

int expand(String s, int l, int r) {
    while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) { l--; r++; }
    return r - l - 1;                                // the loop overshoots by one on each side
}

Python

def longest_palindrome_length(s: str) -> int:
    best = 0
    for c in range(len(s)):
        best = max(best, expand(s, c, c))            # odd length: centered on a character
        best = max(best, expand(s, c, c + 1))        # even length: centered on a gap
    return best


def expand(s: str, lo: int, hi: int) -> int:
    while lo >= 0 and hi < len(s) and s[lo] == s[hi]:   # lo >= 0 matters: s[-1] is the last character
        lo -= 1
        hi += 1
    return hi - lo - 1                               # the loop overshoots by one on each side

There are 2n - 1 centers: n characters and n - 1 gaps between them. Using only character centers misses every even-length palindrome - on "zoom" it answers 1 instead of 2. Each expansion is O(n) in the worst case (a string of one repeated letter), so the total is O(n^2) time and O(1) space.

Where you'll see it

Comparing tag sets or keyword bags ("same words, any order") is the same frequency count over a bigger alphabet. Length limits are where code units bite: a 20-character username limit checked with length() rejects 11 emoji (22 chars), while a database column that counts characters would accept them - so decide which "character" a limit means and check it the same way everywhere.

Which tool for which job?

You needUse
Same letters, small known alphabeta count array
Same letters, any texta hash map of counts, or sorting both
Is it a palindrome?two pointers from the ends
Longest palindromic substringexpand around 2n - 1 centers, or Manacher for O(n)
Building a string in a loopStringBuilder in Java, "".join in Python
Comparing user-entered textnormalize (NFC) and use Locale.ROOT for case

Common mistakes

MistakeWhat happensDo this instead
counts[c - 'a'] on any inputcrashes, or in Python silently miscountscheck the alphabet, or use a map
Reversing a char array with emojibroken surrogate pairsStringBuilder.reverse()
s = s + c in a loopO(n虏): at least 20x slower for 50,000 appendsStringBuilder / "".join
== on stringscompares identity, not textequals (Java), == (Python)
toLowerCase() with the default locale"TITLE" becomes "t谋tle" in TurkishtoLowerCase(Locale.ROOT)
Only character centersmisses even palindromes ("zoom" gives 1)character and gap centers

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Why does counts[c - 'a']++ crash on "Listen" and "Silent", and how do you fix it?

Show answer

'L' - 'a' is negative, so the array index is out of bounds. Lowercase first (if the problem ignores case), index an int[128] by the char itself for ASCII, or count code points in a map for arbitrary text.

2. How many centers does expand-around-center try for a string of length n, and what goes wrong if you only use character centers?

Show answer

2n - 1: n characters (odd-length palindromes) and n - 1 gaps (even-length ones). Without the gaps no even-length palindrome is ever found - "zoom" gives 1 instead of 2 ("oo").

3. Why is s = s + c inside a loop O(n^2), and what should you use instead?

Show answer

Strings are immutable, so each concatenation copies the whole current string into a new object: 1 + 2 + ... + n characters. A StringBuilder appends into a growing buffer in amortized O(1), for O(n) total - as long as you append rather than insert(0, ...).

Key takeaways

  • Anagram = same character counts; a count array does it in O(n), but c - 'a' assumes lowercase a-z.
  • A char is a UTF-16 unit: emoji take two. Count code points for arbitrary text.
  • Find palindromes by expanding from all 2n - 1 centers - odd and even.
  • Strings are immutable: build with StringBuilder.append, not + or insert(0, ...) in a loop.
  • Compare strings with equals, never ==.

Quick revise

The whole skill on one page, for the night before an interview.

This page puts the lesson and the deep dive together. Skim it before practice or an interview, and go back to the full lesson for anything you don't recognize.

Pick the tool

You needUse
Anagram, small alphabetcount array
Anagram, any textmap, or sort
Palindrome checktwo pointers
Longest palindromeexpand 2n - 1 centers; Manacher for O(n)
Build textStringBuilder / "".join
Compare user textNFC plus Locale.ROOT

Snippets worth knowing by heart

Java

int expand(String s, int l, int r) {
    while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) { l--; r++; }
    return r - l - 1;
}
String key = Normalizer.normalize(input, Normalizer.Form.NFC).toLowerCase(Locale.ROOT);

Python

parts = []
for word in words:
    parts.append(word.upper())
result = " ".join(parts)                 # one copy, not O(n^2)

The traps

  • Assumed alphabets: counts[c - 'a'] crashes on other input, or silently miscounts in Python. Check the alphabet, or use a map.
  • Surrogate pairs in Java: reversing a char array breaks emoji. Use StringBuilder.reverse().
  • Concatenation in loops: s = s + c is O(n^2). Use StringBuilder or "".join.
  • == vs equals: in Java == compares identity, not text. Use equals; Python's == is fine.
  • Default-locale case changes: in Turkish "TITLE" lowercases to "t谋tle". Use toLowerCase(Locale.ROOT).

Staff-level points, one line each

  • "a" 脳 5000: 12,502,500 comparisons expanding around centers, 20,000 with Manacher.
  • "馃敟".length() is 2 in Java and 1 in Python. A char-array reverse breaks it; StringBuilder.reverse() doesn't.
  • Composed and decomposed "caf茅" aren't equal until NFC-normalized.
  • Turkish toLowerCase() turned "TITLE" into "t谋tle"; "stra脽e" uppercases to "STRASSE", 6 to 7 characters.
  • 50,000 + appends were at least 20x slower than a StringBuilder.

Say it in an interview

  • "Anagrams are about counts, palindromes about symmetry."
  • "There are 2n - 1 centers, so even-length palindromes aren't missed."
  • "For O(n), Manacher reuses mirrored radii."
  • "With real user text I'd normalize, and use Locale.ROOT for case."

Practice

This skill comes with 7 multiple-choice questions that tell you which misconception a wrong answer reveals and 3 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice String Manipulation Basics free

Valid Anagram

EasyFreeCoding problemJava 路 Python

Two strings are anagrams when one is the other with its letters shuffled: the same letters, each used the same number of times. Return whether t is an anagram of s.

Valid Palindrome

EasyFreeCoding problemJava 路 Python

Strip a line of text down to its letters and digits, ignore upper and lower case, and check whether what's left reads the same in both directions. Return whether it does.

Longest Palindromic Substring (Length)

MediumProCoding problemJava 路 Python

Return the length of the longest contiguous piece of s that reads the same forwards and backwards.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice String Manipulation Basics free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card 路 7-day Pro trial 路 Cancel anytime