2414. Length of the Longest Alphabetical Continuous Substring
Problem Description
You need to find the length of the longest substring in a given string where the characters are consecutive letters in alphabetical order.
An alphabetical continuous string is defined as a sequence of consecutive letters from the alphabet. This means it's any substring that appears in "abcdefghijklmnopqrstuvwxyz"
exactly as written.
For example:
"abc"
is valid because the letters appear consecutively in the alphabet"acb"
is not valid because it skips'b'
between'a'
and'c'
"za"
is not valid because'z'
doesn't come immediately before'a'
in the alphabet
Given a string s
containing only lowercase letters, you need to return the length of the longest substring where each character is exactly one letter after the previous character in alphabetical order.
The solution works by traversing the string and checking if each character's ASCII value is exactly 1 more than the previous character. It maintains a counter cnt
for the current consecutive sequence length and ans
for the maximum length found. When characters are consecutive (y - x == 1
), the counter increases; otherwise, it resets to 1. The function returns the maximum length found.
Intuition
The key insight is that consecutive letters in the alphabet have consecutive ASCII values. For instance, 'a'
has ASCII value 97, 'b'
has 98, and 'c'
has 99. This means if two characters are alphabetically consecutive, their ASCII values will differ by exactly 1.
To find the longest alphabetical continuous substring, we can scan through the string once and check each adjacent pair of characters. If the second character's ASCII value is exactly 1 more than the first character's ASCII value, they form a continuous sequence.
We need to track two things:
- The length of the current continuous sequence we're building
- The maximum length we've seen so far
As we traverse the string:
- When we find consecutive letters (difference of 1 in ASCII values), we extend our current sequence
- When we find non-consecutive letters, we know the current sequence has ended and must start counting a new sequence from length 1
- We continuously update our maximum whenever we extend a sequence
This approach works because we're essentially looking for the longest "chain" of characters where each link (character) connects perfectly to the next one (exactly +1 in ASCII value). Once a chain breaks, we start building a new one, but we remember the longest chain we've found.
The use of pairwise
with map(ord, s)
elegantly gives us consecutive pairs of ASCII values to compare, making the check y - x == 1
straightforward and efficient.
Solution Approach
The solution uses a single pass algorithm to traverse the string and find the longest alphabetical continuous substring.
Variables Used:
ans
: Tracks the maximum length of alphabetical continuous substring found so farcnt
: Tracks the length of the current continuous substring being examined
Algorithm Steps:
-
Initialize counters: Start with
ans = cnt = 1
since any single character forms a valid substring of length 1. -
Traverse adjacent pairs: Use
pairwise(map(ord, s))
to:- Convert each character to its ASCII value using
map(ord, s)
- Get consecutive pairs of ASCII values
(x, y)
usingpairwise
- Convert each character to its ASCII value using
-
Check continuity: For each pair
(x, y)
:- If
y - x == 1
: The characters are consecutive in the alphabet- Increment
cnt
by 1 to extend the current sequence - Update
ans = max(ans, cnt)
to record the longest sequence found
- Increment
- Otherwise: The sequence is broken
- Reset
cnt = 1
to start counting a new sequence
- Reset
- If
-
Return result: After traversing all pairs, return
ans
which contains the length of the longest alphabetical continuous substring.
Example Walkthrough:
For string "abcdxyz"
:
'a'
,'b'
:98 - 97 = 1
→cnt = 2
,ans = 2
'b'
,'c'
:99 - 98 = 1
→cnt = 3
,ans = 3
'c'
,'d'
:100 - 99 = 1
→cnt = 4
,ans = 4
'd'
,'x'
:120 - 100 ≠ 1
→cnt = 1
,ans = 4
'x'
,'y'
:121 - 120 = 1
→cnt = 2
,ans = 4
'y'
,'z'
:122 - 121 = 1
→cnt = 3
,ans = 4
The function returns 4
(the substring "abcd"
).
Time Complexity: O(n)
where n
is the length of the string, as we traverse it once.
Space Complexity: O(1)
as we only use a constant amount of extra space for the counters.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with the string "bdface"
.
Initial Setup:
ans = 1
(maximum length found so far)cnt = 1
(current sequence length)
Step-by-step Processing:
-
Compare 'b' and 'd':
- ASCII values: 'b' = 98, 'd' = 100
- Difference: 100 - 98 = 2 (not equal to 1)
- Characters are NOT consecutive
- Reset
cnt = 1
ans
remains 1
-
Compare 'd' and 'f':
- ASCII values: 'd' = 100, 'f' = 102
- Difference: 102 - 100 = 2 (not equal to 1)
- Characters are NOT consecutive
- Reset
cnt = 1
ans
remains 1
-
Compare 'f' and 'a':
- ASCII values: 'f' = 102, 'a' = 97
- Difference: 97 - 102 = -5 (not equal to 1)
- Characters are NOT consecutive
- Reset
cnt = 1
ans
remains 1
-
Compare 'a' and 'c':
- ASCII values: 'a' = 97, 'c' = 99
- Difference: 99 - 97 = 2 (not equal to 1)
- Characters are NOT consecutive
- Reset
cnt = 1
ans
remains 1
-
Compare 'c' and 'e':
- ASCII values: 'c' = 99, 'e' = 101
- Difference: 101 - 99 = 2 (not equal to 1)
- Characters are NOT consecutive
- Reset
cnt = 1
ans
remains 1
Result: The function returns 1
since no consecutive alphabetical sequences were found.
Another Example with a Valid Sequence:
Let's try "xyzabc"
:
- 'x' and 'y': 121 - 120 = 1 ✓ →
cnt = 2
,ans = 2
- 'y' and 'z': 122 - 121 = 1 ✓ →
cnt = 3
,ans = 3
- 'z' and 'a': 97 - 122 = -25 ✗ →
cnt = 1
,ans = 3
- 'a' and 'b': 98 - 97 = 1 ✓ →
cnt = 2
,ans = 3
- 'b' and 'c': 99 - 98 = 1 ✓ →
cnt = 3
,ans = 3
Result: Returns 3
for both "xyz" and "abc" substrings (tied for longest).
Solution Implementation
1class Solution:
2 def longestContinuousSubstring(self, s: str) -> int:
3 """
4 Find the length of the longest continuous substring where each character
5 is exactly one more than the previous character in alphabetical order.
6
7 Args:
8 s: Input string containing lowercase English letters
9
10 Returns:
11 Length of the longest continuous alphabetical substring
12 """
13 # Import pairwise from itertools (Python 3.10+)
14 from itertools import pairwise
15
16 # Initialize the maximum length and current streak counter
17 max_length = 1 # At least one character forms a valid substring
18 current_streak = 1 # Current consecutive alphabetical sequence length
19
20 # Iterate through adjacent character pairs
21 # Convert characters to ASCII values for comparison
22 for current_char, next_char in pairwise(map(ord, s)):
23 # Check if next character is exactly one more than current
24 # (e.g., 'a' -> 'b', 'b' -> 'c')
25 if next_char - current_char == 1:
26 # Extend the current streak
27 current_streak += 1
28 # Update maximum length if current streak is longer
29 max_length = max(max_length, current_streak)
30 else:
31 # Reset streak counter when sequence breaks
32 current_streak = 1
33
34 return max_length
35
1class Solution {
2 public int longestContinuousSubstring(String s) {
3 // Initialize the maximum length found so far
4 int maxLength = 1;
5
6 // Initialize the current consecutive sequence length
7 int currentLength = 1;
8
9 // Iterate through the string starting from the second character
10 for (int i = 1; i < s.length(); i++) {
11 // Check if current character is consecutive to the previous one
12 // (e.g., 'b' follows 'a', 'c' follows 'b', etc.)
13 if (s.charAt(i) - s.charAt(i - 1) == 1) {
14 // Increment current sequence length
15 currentLength++;
16
17 // Update maximum length if current sequence is longer
18 maxLength = Math.max(maxLength, currentLength);
19 } else {
20 // Reset current sequence length when consecutive pattern breaks
21 currentLength = 1;
22 }
23 }
24
25 // Return the length of the longest alphabetically continuous substring
26 return maxLength;
27 }
28}
29
1class Solution {
2public:
3 int longestContinuousSubstring(string s) {
4 // Initialize the maximum length and current streak counter
5 int maxLength = 1; // At least one character forms a valid substring
6 int currentStreak = 1; // Current consecutive alphabetical sequence length
7
8 // Iterate through the string starting from the second character
9 for (int i = 1; i < s.size(); ++i) {
10 // Check if current character is exactly one more than previous character
11 // (consecutive in alphabetical order)
12 if (s[i] - s[i - 1] == 1) {
13 // Extend the current streak
14 currentStreak++;
15 // Update maximum length if current streak is longer
16 maxLength = max(maxLength, currentStreak);
17 } else {
18 // Reset streak counter when sequence breaks
19 currentStreak = 1;
20 }
21 }
22
23 return maxLength;
24 }
25};
26
1/**
2 * Finds the length of the longest continuous substring where each character
3 * is exactly one ASCII value greater than the previous character.
4 * @param s - The input string to analyze
5 * @returns The length of the longest continuous alphabetical substring
6 */
7function longestContinuousSubstring(s: string): number {
8 // Initialize the maximum length found and current sequence length
9 let maxLength: number = 1;
10 let currentLength: number = 1;
11
12 // Iterate through the string starting from the second character
13 for (let i: number = 1; i < s.length; i++) {
14 // Check if current character is exactly one ASCII value greater than previous
15 if (s.charCodeAt(i) - s.charCodeAt(i - 1) === 1) {
16 // Increment current sequence length
17 currentLength++;
18 // Update maximum length if current sequence is longer
19 maxLength = Math.max(maxLength, currentLength);
20 } else {
21 // Reset current sequence length when continuity breaks
22 currentLength = 1;
23 }
24 }
25
26 return maxLength;
27}
28
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string s
. The algorithm iterates through the string once using pairwise
, which creates pairs of consecutive elements. Since we visit each character exactly once (except the first character which only appears as the second element in the first pair), the time complexity is linear.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space for variables ans
and cnt
. While pairwise
and map
create iterators, they don't store the entire transformed sequence in memory - they generate values on-the-fly. The map(ord, s)
converts characters to their ASCII values one at a time as needed, and pairwise
yields consecutive pairs without creating a list of all pairs. Therefore, only a constant amount of additional memory is used regardless of the input size.
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 counters, which can cause issues with single-character strings.
Incorrect approach:
def longestContinuousSubstring(self, s: str) -> int:
if not s: # Only checking for empty string
return 0
max_length = 0 # Wrong: should start at 1
current_streak = 0 # Wrong: should start at 1
# ...
Why it fails: For a single character string like "a"
, the pairwise iteration produces no pairs, so the loop never executes. If max_length
starts at 0, it returns 0 instead of 1.
Correct approach:
max_length = 1 # Any single character is a valid substring of length 1 current_streak = 1 # Start counting from the first character
2. Incorrect Update of Maximum Length
Another pitfall is updating max_length
in the wrong place or forgetting to update it when the streak increases.
Incorrect approach:
for current_char, next_char in pairwise(map(ord, s)):
if next_char - current_char == 1:
current_streak += 1
# Forgot to update max_length here!
else:
max_length = max(max_length, current_streak) # Only updating on break
current_streak = 1
Why it fails: If the longest continuous substring is at the end of the string (like "xyzabc"
where "abc"
is the longest), the maximum won't be updated since there's no break after it.
Correct approach:
if next_char - current_char == 1:
current_streak += 1
max_length = max(max_length, current_streak) # Update immediately
3. Using Wrong Comparison for Consecutive Characters
Some might mistakenly check if characters are simply different or in ascending order, rather than exactly consecutive.
Incorrect approach:
if next_char > current_char: # Wrong: just checking if ascending current_streak += 1
Why it fails: This would incorrectly count "ace"
as a continuous substring of length 3, when it should only count substrings where each character is exactly one more than the previous.
Correct approach:
if next_char - current_char == 1: # Must be exactly 1 apart current_streak += 1
4. Python Version Compatibility Issue
The pairwise
function is only available in Python 3.10+. Using it in earlier versions causes an ImportError.
Solution for older Python versions:
def longestContinuousSubstring(self, s: str) -> int:
if len(s) <= 1:
return len(s)
max_length = 1
current_streak = 1
# Manual iteration instead of pairwise
for i in range(1, len(s)):
if ord(s[i]) - ord(s[i-1]) == 1:
current_streak += 1
max_length = max(max_length, current_streak)
else:
current_streak = 1
return max_length
Which algorithm is best for finding the shortest distance between two points in an unweighted graph?
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!