1446. Consecutive Characters
Problem Description
You are given a string s
. The power of a string is defined as the maximum length of a non-empty substring that contains only one unique character (all characters in the substring are the same).
Your task is to find and return the power of the given string s
.
For example:
- If
s = "leetcode"
, the power is2
because "ee" is the longest substring with only one unique character - If
s = "abbcccddddeeeeedcba"
, the power is5
because "eeeee" is the longest substring with only one unique character - If
s = "triplepillooooow"
, the power is5
because "ooooo" is the longest substring with only one unique character
The solution works by traversing through the string and keeping track of consecutive identical characters. It uses a variable t
to count the current streak of identical characters. When it encounters a different character, it resets the counter to 1. Throughout the traversal, it maintains the maximum streak found, which represents the power of the string.
Intuition
To find the longest substring with only one unique character, we need to identify consecutive sequences of the same character. The key insight is that we can solve this problem in a single pass through the string by tracking consecutive identical characters.
Think of it like counting steps while walking - every time you take a step in the same direction, you increment your counter. When you change direction, you reset your counter to 1 and start counting again. Throughout your walk, you keep track of the maximum number of consecutive steps in any single direction.
Similarly, as we traverse the string character by character, we can compare each character with its previous one. If they match, we're extending our current sequence of identical characters, so we increment our counter t
. If they don't match, we've encountered a new character, which starts a new sequence, so we reset t = 1
.
The beauty of this approach is its simplicity - we don't need to generate all possible substrings or use complex data structures. By using the pairwise
function to look at adjacent character pairs (a, b)
, we can elegantly check if consecutive characters are the same. We maintain the maximum length seen so far in ans
, updating it whenever we find a longer sequence.
This greedy approach works because the power of a string depends only on finding the maximum length, not on tracking all sequences. We can determine the answer in O(n)
time with just a single traversal.
Solution Approach
The implementation uses a traversal and counting technique to find the maximum length of consecutive identical characters.
We initialize two variables:
ans = 1
: Stores the maximum power found so far (initialized to 1 since any single character has power 1)t = 1
: Tracks the current length of consecutive identical characters
The algorithm leverages Python's pairwise
function to iterate through adjacent character pairs in the string. For each pair (a, b)
:
-
If characters match (
a == b
):- Increment the current streak:
t += 1
- Update the maximum if needed:
ans = max(ans, t)
- This means we're extending our current sequence of identical characters
- Increment the current streak:
-
If characters don't match (
a != b
):- Reset the counter:
t = 1
- This indicates we've encountered a different character and must start counting a new sequence
- Reset the counter:
The pairwise
function creates sliding windows of size 2, giving us pairs like:
- For string
"aabbb"
, we get pairs:('a','a')
,('a','b')
,('b','b')
,('b','b')
This approach ensures we examine every transition point in the string where characters might change or continue. By maintaining the running maximum in ans
, we capture the longest sequence without needing to store all sequences.
The time complexity is O(n)
where n
is the length of the string, as we traverse the string once. The space complexity is O(1)
as we only use a constant amount of extra space for our variables.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with the string s = "abbcccddddeeeeedcba"
.
We initialize:
ans = 1
(maximum power found so far)t = 1
(current streak of identical characters)
Now we traverse through adjacent character pairs:
-
Pair ('a', 'b'): Different characters
t = 1
(reset counter)ans = 1
-
Pair ('b', 'b'): Same characters
t = 2
(increment streak)ans = max(1, 2) = 2
-
Pair ('b', 'c'): Different characters
t = 1
(reset counter)ans = 2
-
Pair ('c', 'c'): Same characters
t = 2
ans = max(2, 2) = 2
-
Pair ('c', 'c'): Same characters
t = 3
ans = max(2, 3) = 3
-
Pair ('c', 'd'): Different characters
t = 1
ans = 3
-
Pairs ('d', 'd'), ('d', 'd'), ('d', 'd'): All same characters
t
increases: 2 → 3 → 4ans = max(3, 4) = 4
-
Pair ('d', 'e'): Different characters
t = 1
ans = 4
-
Pairs ('e', 'e'), ('e', 'e'), ('e', 'e'), ('e', 'e'): All same characters
t
increases: 2 → 3 → 4 → 5ans = max(4, 5) = 5
-
Remaining pairs lead to different characters or shorter streaks
Final answer: 5 (from the substring "eeeee")
Solution Implementation
1class Solution:
2 def maxPower(self, s: str) -> int:
3 # Initialize the maximum length and current streak counter
4 max_length = 1
5 current_streak = 1
6
7 # Iterate through consecutive character pairs in the string
8 for i in range(len(s) - 1):
9 # Check if current character equals the next character
10 if s[i] == s[i + 1]:
11 # Increment the current streak counter
12 current_streak += 1
13 # Update maximum length if current streak is longer
14 max_length = max(max_length, current_streak)
15 else:
16 # Reset streak counter when characters differ
17 current_streak = 1
18
19 return max_length
20
1class Solution {
2 /**
3 * Finds the maximum power of a string, where power is defined as
4 * the length of the longest substring containing only one unique character.
5 *
6 * @param s the input string
7 * @return the maximum length of a substring with consecutive identical characters
8 */
9 public int maxPower(String s) {
10 // Initialize the maximum power found so far
11 int maxConsecutiveLength = 1;
12
13 // Track the current consecutive character count
14 int currentConsecutiveCount = 1;
15
16 // Iterate through the string starting from the second character
17 for (int i = 1; i < s.length(); i++) {
18 // Check if current character matches the previous character
19 if (s.charAt(i) == s.charAt(i - 1)) {
20 // Increment the consecutive count
21 currentConsecutiveCount++;
22
23 // Update maximum if current streak is longer
24 maxConsecutiveLength = Math.max(maxConsecutiveLength, currentConsecutiveCount);
25 } else {
26 // Reset counter when characters don't match
27 currentConsecutiveCount = 1;
28 }
29 }
30
31 return maxConsecutiveLength;
32 }
33}
34
1class Solution {
2public:
3 int maxPower(string s) {
4 // Initialize the maximum consecutive count to 1 (minimum possible)
5 int maxConsecutive = 1;
6
7 // Track the current consecutive count
8 int currentCount = 1;
9
10 // Iterate through the string starting from the second character
11 for (int i = 1; i < s.size(); ++i) {
12 // Check if current character matches the previous one
13 if (s[i] == s[i - 1]) {
14 // Increment current consecutive count
15 currentCount++;
16 // Update maximum if current count is larger
17 maxConsecutive = max(maxConsecutive, currentCount);
18 } else {
19 // Reset count when characters don't match
20 currentCount = 1;
21 }
22 }
23
24 return maxConsecutive;
25 }
26};
27
1/**
2 * Finds the length of the longest substring containing the same character
3 * @param s - Input string to analyze
4 * @returns The maximum power (length of longest consecutive same characters)
5 */
6function maxPower(s: string): number {
7 // Track the maximum consecutive count found so far
8 let maxConsecutiveCount: number = 1;
9
10 // Track the current consecutive count
11 let currentConsecutiveCount: number = 1;
12
13 // Iterate through the string starting from the second character
14 for (let i: number = 1; i < s.length; i++) {
15 // Check if current character matches the previous character
16 if (s[i] === s[i - 1]) {
17 // Increment current consecutive count
18 currentConsecutiveCount++;
19 // Update maximum if current count is larger
20 maxConsecutiveCount = Math.max(maxConsecutiveCount, currentConsecutiveCount);
21 } else {
22 // Reset current count when characters don't match
23 currentConsecutiveCount = 1;
24 }
25 }
26
27 return maxConsecutiveCount;
28}
29
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string s
. This is because the pairwise
function iterates through the string once, creating pairs of consecutive characters. Each pair is processed exactly once in the for loop, performing constant-time operations (comparison, increment, and max calculation) for each pair. Since there are n-1
pairs for a string of length n
, the overall time complexity is linear.
The space complexity is O(1)
. The algorithm only uses a fixed amount of extra space regardless of the input size. The variables ans
and t
are simple integers that don't scale with the input. The pairwise
function generates pairs on-the-fly without storing all pairs in memory, using an iterator that maintains only a constant amount of state. Therefore, the space usage remains constant.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Forgetting to Handle Single Character Strings
A common mistake is not properly initializing the variables or not handling edge cases where the string has only one character.
Pitfall Example:
def maxPower(self, s: str) -> int:
max_length = 0 # Wrong initialization!
current_streak = 0 # Wrong initialization!
for i in range(len(s) - 1):
if s[i] == s[i + 1]:
current_streak += 1
max_length = max(max_length, current_streak)
else:
current_streak = 1
return max_length # Returns 0 for single character strings!
Solution: Always initialize both max_length
and current_streak
to 1, since any non-empty string has at least a power of 1.
2. Not Updating Maximum for the Last Streak
When the longest consecutive sequence occurs at the end of the string, failing to update the maximum after the loop can lead to incorrect results.
Pitfall Example:
def maxPower(self, s: str) -> int:
max_length = 1
current_streak = 1
for i in range(len(s) - 1):
if s[i] == s[i + 1]:
current_streak += 1
# Only updating here might miss the final streak
else:
max_length = max(max_length, current_streak)
current_streak = 1
return max_length # Misses updating for string ending with longest streak!
Solution: Either update max_length
inside the matching condition (as shown in the correct solution) or add a final check after the loop: return max(max_length, current_streak)
.
3. Off-by-One Errors in Loop Range
Using incorrect loop boundaries can cause index out of bounds errors or miss character comparisons.
Pitfall Example:
def maxPower(self, s: str) -> int:
max_length = 1
current_streak = 1
for i in range(len(s)): # Goes up to len(s) - 1
if s[i] == s[i + 1]: # IndexError when i = len(s) - 1!
current_streak += 1
max_length = max(max_length, current_streak)
else:
current_streak = 1
return max_length
Solution: Always use range(len(s) - 1)
when comparing consecutive elements to avoid accessing index out of bounds.
4. Resetting Counter to 0 Instead of 1
When encountering a different character, resetting the counter to 0 instead of 1 leads to incorrect counting.
Pitfall Example:
def maxPower(self, s: str) -> int:
max_length = 1
current_streak = 1
for i in range(len(s) - 1):
if s[i] == s[i + 1]:
current_streak += 1
max_length = max(max_length, current_streak)
else:
current_streak = 0 # Wrong! Should be 1
return max_length
Solution: Always reset current_streak
to 1 when characters differ, as the new character itself forms a streak of length 1.
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!