Skip to content
← All posts

Consecutive Characters: Finding the Power of a String

5 min read
leetcodeproblemeasystrings

LeetCode 1446, Consecutive Characters, defines the "power" of a string as the length of the longest substring of consecutive identical characters. Given a string s, return its power.

For example, "leetcode" has a power of 2 because "ee" is the longest run of one repeated character. The string "abbcccddddeeeeedcba" has a power of 5 because of the five consecutive 'e' characters in the middle.

01234567leetcodepower = 2longest consecutive run
The string "leetcode" has a power of 2, because "ee" is the longest substring of consecutive identical characters.

Why this problem matters

At first glance, this looks like a warm-up problem you could solve in your sleep. And it is one of the easier LeetCode problems. But the pattern hiding inside it shows up again and again in harder string problems: tracking a running streak and resetting it when a condition breaks. That same logic is at the core of string compression, run-length encoding, and several sliding window problems.

If you can write the streak-counting loop without hesitation, you have a building block that plugs directly into problems like String Compression (LeetCode 443) and Count and Say (LeetCode 38). Both require scanning consecutive identical characters, counting them, and acting on each group. The difference is what you do with the groups, not how you find them.

This problem also tests whether you can avoid overengineering. You do not need a hash map, a stack, or a sliding window. You need one variable for the current streak and one for the maximum. That is it.

The key insight

You only need a single pass through the string. At each index, compare the current character to the previous one. If they match, the streak continues and you increment a counter. If they differ, the streak breaks and you reset the counter to 1. After each step, update the maximum if the current streak exceeds it.

This works because consecutive identical characters form contiguous groups. You never need to look back further than one position. The current character either extends the streak or starts a new one.

The solution

def maxPower(s):
    max_power = 1
    streak = 1
    for i in range(1, len(s)):
        if s[i] == s[i - 1]:
            streak += 1
        else:
            streak = 1
        max_power = max(max_power, streak)
    return max_power

The loop starts at index 1 because there is nothing to compare index 0 against. Both max_power and streak start at 1 because a single character is always a run of length 1.

At each position, the comparison s[i] == s[i - 1] decides whether to grow or reset the streak. Then max_power captures the best streak seen so far. By the time you reach the end of the string, max_power holds the answer.

You can also write this with a for ch in s loop and a variable tracking the previous character. The logic is identical, but the index-based version makes the comparison clearer when you are tracing through examples on a whiteboard.

Visual walkthrough

Here is a step-by-step trace of the algorithm on the string "abbcccddddeeeeedcba". Watch how the streak counter grows within each group of identical characters and resets when the character changes.

Step 1: Initialize at index 0

streak = 1max = 1
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

Start with streak = 1 and maxPower = 1. The first character 'a' is a run of length 1.

Step 2: New character at index 1

streak = 1max = 1
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

s[1] = 'b' differs from s[0] = 'a'. Reset streak to 1. maxPower stays at 1.

Step 3: Streak grows at index 2

streak = 2max = 2
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

s[2] = 'b' matches s[1]. Streak grows to 2. Update maxPower to 2.

Step 4: New streak at index 3

streak = 3max = 3
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

The 'c' run spans indices 3-5 (length 3). maxPower updates to 3.

Step 5: Longer streak found

streak = 4max = 4
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

The 'd' run spans indices 6-9 (length 4). maxPower updates to 4.

Step 6: New maximum found

streak = 5max = 5
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

The 'e' run spans indices 10-14 (length 5). maxPower updates to 5. This is the longest run in the string.

Step 7: Remaining characters

streak = 1max = 5
0123456789101112131415161718abbcccddddeeeeedcba
pointer
streak
max run

The tail 'd','c','b','a' are each runs of length 1. maxPower remains 5. Return 5.

The algorithm scans left to right in a single pass. The streak grows through the 'b', 'c', 'd', and 'e' groups, updating maxPower each time a new longest run is found. Once the 'e' run ends, the remaining characters produce streaks of length 1, and the final answer is 5.

Complexity analysis

ApproachTimeSpace
Single passO(n)O(1)

The time is O(n) because you visit each character exactly once. There are no nested loops, no hash maps to build, and no sorting.

The space is O(1) because you only use two integer variables (streak and max_power) regardless of the input size. The string itself is read-only.

The building blocks

1. Streak counting

streak = 1
for i in range(1, len(s)):
    if s[i] == s[i - 1]:
        streak += 1
    else:
        streak = 1

This is the core pattern: maintain a counter that grows when consecutive elements match and resets when they differ. You will see this exact loop structure in string compression, run-length encoding, and any problem that asks you to process groups of identical adjacent elements. The key detail is starting streak at 1 (not 0), because the first character of any group counts.

2. Running maximum

max_power = max(max_power, streak)

After each update to the streak, check whether it is the new maximum. This is the same "track the best so far" pattern used in problems like Maximum Subarray and Best Time to Buy and Sell Stock. You compute a local value at each step and compare it against a global best. Placing this update after every iteration (not just when the streak resets) ensures you do not miss the case where the longest run extends to the very end of the string.

Edge cases

  • Single character string. The string "a" has power 1. The loop body never executes, and the initial value of max_power = 1 is returned.
  • All identical characters. A string like "aaaa" has power equal to its length. The streak never resets, and max_power matches streak at every step.
  • All distinct characters. A string like "abcde" has power 1. The streak resets to 1 at every index, and max_power never grows past 1.
  • Longest run at the end. For "abccc", the longest run is at the tail. Because max_power is updated on every iteration (not just when the streak breaks), this case is handled correctly.
  • Two characters alternating. A string like "ababab" has power 1. Each character differs from the previous one, so the streak resets every step.

From understanding to recall

Reading through this solution takes less than a minute. The logic is clear: compare, grow or reset, update max. But when you sit down to code it from memory a week later, small details start to slip. Do you initialize streak to 0 or 1? Does the loop start at index 0 or 1? Do you update max_power inside the if or after it?

These are exactly the kinds of details that spaced repetition is designed to lock in. You drill the streak-counting loop as one brick and the running-maximum update as another. Each rep takes thirty seconds. After a few rounds at increasing intervals, you write the solution without pausing to think about initialization or off-by-one errors.

The payoff goes beyond this single problem. The streak-counting pattern is a building block that plugs into String Compression, Count and Say, and run-length encoding problems. When you own the brick, you assemble it instantly in any context.

Related posts

CodeBricks breaks problems like Consecutive Characters into small, drillable building blocks and schedules them with spaced repetition. Instead of re-reading solutions, you practice writing them from memory at the intervals that maximize long-term retention.