Facebook Pixel

2414. Length of the Longest Alphabetical Continuous Substring

MediumString
Leetcode Link

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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. The length of the current continuous sequence we're building
  2. 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 far
  • cnt: Tracks the length of the current continuous substring being examined

Algorithm Steps:

  1. Initialize counters: Start with ans = cnt = 1 since any single character forms a valid substring of length 1.

  2. 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) using pairwise
  3. 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
    • Otherwise: The sequence is broken
      • Reset cnt = 1 to start counting a new sequence
  4. 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 = 1cnt = 2, ans = 2
  • 'b', 'c': 99 - 98 = 1cnt = 3, ans = 3
  • 'c', 'd': 100 - 99 = 1cnt = 4, ans = 4
  • 'd', 'x': 120 - 100 ≠ 1cnt = 1, ans = 4
  • 'x', 'y': 121 - 120 = 1cnt = 2, ans = 4
  • 'y', 'z': 122 - 121 = 1cnt = 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 Evaluator

Example 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:

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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":

  1. 'x' and 'y': 121 - 120 = 1 ✓ → cnt = 2, ans = 2
  2. 'y' and 'z': 122 - 121 = 1 ✓ → cnt = 3, ans = 3
  3. 'z' and 'a': 97 - 122 = -25 ✗ → cnt = 1, ans = 3
  4. 'a' and 'b': 98 - 97 = 1 ✓ → cnt = 2, ans = 3
  5. '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
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which algorithm is best for finding the shortest distance between two points in an unweighted graph?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More