Minimum Number of Steps to Make Two Strings Anagram
LeetCode 1347. Minimum Number of Steps to Make Two Strings Anagram is a clean medium-difficulty problem that tests whether you can think in terms of character frequencies instead of trying to rearrange strings directly. If you have already solved Valid Anagram and Group Anagrams, this one builds on the exact same foundation.
The problem
You are given two strings s and t of equal length. In one step, you can choose any character in t and replace it with any other character. Return the minimum number of steps to make t an anagram of s.
Two strings are anagrams if they contain the same characters with the same frequencies. The order does not matter.
Example 1: s = "bab", t = "aba" returns 1. You can replace one 'a' in t with 'b' to get "bba", which is an anagram of "bab".
Example 2: s = "leetcode", t = "practice" returns 5. You need to replace 5 characters in t to match the character frequencies of s.
The key insight
You do not need to figure out which specific characters to replace or where. You just need to know how many replacements are necessary.
Think about it this way: count the frequency of every character in both strings. For each character where s has more occurrences than t, that difference represents characters you must add to t. Since the strings are the same length, every character you add means one replacement.
The answer is simply the sum of all positive differences between the frequency counts of s and t.
Why does this work? The strings have equal length, so the total number of characters that s has in excess must equal the total number of characters that t has in excess. You replace the characters that t has too many of with the characters that t is missing.
The solution
from collections import Counter
def min_steps(s: str, t: str) -> int:
count_s = Counter(s)
count_t = Counter(t)
steps = 0
for ch in count_s:
diff = count_s[ch] - count_t.get(ch, 0)
if diff > 0:
steps += diff
return steps
Step-by-step walkthrough
Let's trace through both examples to see exactly how the counting works.
Step 1: Count character frequencies in s = "bab"
We scan s and record how many times each character appears.
Step 2: Count character frequencies in t = "aba"
Same process for t. Now we have both frequency maps.
Step 3: Compare frequencies and sum the excess
For each character, if s has more than t, we add the difference. 'b' has +1 excess in s, so 1 step.
Step 4: Larger example with s = "leetcode", t = "practice"
Five characters have excess in s (d:+1, l:+1, o:+1, t:+1, e remaining after accounting for shared e). Total = 5 steps.
The algorithm is the same in every case. Count both strings, find the excess, and sum it up. No sorting, no rearranging, no complicated logic.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Frequency counting | O(n) | O(1) |
Time: O(n). You iterate through each string once to build the frequency maps, then iterate through at most 26 characters to compute the difference. Everything is linear in the length of the input.
Space: O(1). The frequency maps hold at most 26 entries (lowercase English letters). This is constant space regardless of input size.
Since the problem guarantees lowercase English letters only, you could use a fixed-size array of 26 instead of a Counter. The Counter version is more readable, and the performance difference is negligible.
The building blocks
This problem is built from two core patterns that appear in many other problems.
Frequency counting
The foundation of this problem is counting character frequencies, which is the same technique used in Valid Anagram and Group Anagrams. The template is simple:
from collections import Counter
freq = Counter(s)
Once you have frequency maps for both inputs, the comparison is trivial. This pattern shows up any time you need to know "how many of each element exist" rather than caring about order or position.
Difference accumulation
The second building block is computing the one-sided difference between two frequency maps. Instead of comparing every pair of entries, you only sum the positive differences:
steps = 0
for ch in count_s:
diff = count_s[ch] - count_t.get(ch, 0)
if diff > 0:
steps += diff
This pattern appears in problems where you need to measure the "gap" between two distributions. The key insight is that you only need to count one direction (the excess in s) because the strings are equal length, so the total excess in s must equal the total deficit.
Edge cases to watch for
- Identical strings. If
sandtare already the same string, every frequency matches and the answer is 0. No special handling needed. - Completely different strings. If
sandtshare no characters at all, every character intmust be replaced. The answer equals the length of the strings. - Single character strings.
s = "a",t = "b"returns 1.s = "a",t = "a"returns 0. The algorithm handles this without any changes. - All same character.
s = "aaaa",t = "bbbb"returns 4. Every character intmust be replaced.
From understanding to recall
This problem feels almost trivial once you see the frequency-counting approach. "Obviously you just count both strings and sum the positive differences." But the real skill is recognizing when to reach for frequency counting in the first place.
The pattern here is not specific to anagrams. It applies any time you need to compare two collections by their composition rather than their order. Spaced repetition helps you build that recognition. You practice the frequency-counting template at increasing intervals until the moment you see "compare two things by what they contain," the Counter pattern fires automatically.
You stop searching for the approach and start searching for the details.
Related posts
- Valid Anagram - The yes/no version of the same frequency comparison technique
- Group Anagrams - Using sorted keys or frequency counts to group words by anagram equivalence
- Find All Anagrams in a String - Sliding window plus frequency counting to find all anagram substrings