Talentd
FleetCode
Make and follow sheets.Sign in

Maximum Length Substring With Two Occurrences solution and explanation

EasyHash TableSliding WindowString5 min read77.4% acceptanceUpdated 9 Apr 2026
3090 Maximum Length Substring With Two Occurrences || Brute Force to Optimal ✅ || Sliding WindowAyush Rao · 7:05 · 2K viewsWatch on YouTube
8 more videos on this problem
  1. 3090 Maximum Length Substring With Two Occurrences || Brute Force to Optimal ✅ || Sliding WindowAyush Rao · 7:05 · 2K views
  2. Leetcode | 3090. Maximum Length Substring With Two Occurrences | Easy | Java SolutionDeveloper Docs · 6:25 · 903 views
  3. 100245 Maximum Length Substring With Two Occurrences | leetcode || contest 390 || solved || java |Ssquare · 1:25 · 735 views
  4. 3090. Maximum Length Substring With Two Occurrences | Weekly Contest 390 | Sliding Window | C++Priyanshi Porwal · 13:31 · 642 views
  5. 3090. Maximum Length Substring With Two Occurrences (Leetcode Easy)Programming Live with Larry · 4:25 · 578 views
  6. Leetcode 3090 Maximum Length Substring With Two OccurrencesTech Diet · 7:02 · 205 views
  7. LEETCODE | Maximum Length Substring With Two Occurrences | the_cozy__notebook · 0:17 · 169 views
  8. Leetcode 3090 Maximum Length Substring With Two OccurrencesLuc Taylor · 4:23 · 148 views
  9. 3090. Maximum Length Substring With Two Occurrences || LC Weekly 390 || 2 Pointers | Sliding Window🔥Code With Anubhav · 27:09 · 72 views

The problem

Given a string s, return the maximum length of a substring such that it contains at most two occurrences of each character.

Example 1:

Input: s = "bcbbbcba"

Output: 4

Explanation:

The following substring has a length of 4 and contains at most two occurrences of each character: "bcbbbcba".

Example 2:

Input: s = "aaaa"

Output: 2

Explanation:

The following substring has a length of 2 and contains at most two occurrences of each character: "aaaa".

Constraints:

  • 2 <= s.length <= 100
  • s consists only of lowercase English letters.

Approach overview

Problem Overview: Given a string s, find the maximum length of a substring where every character appears at most two times. The substring must remain contiguous, so the challenge is maintaining character counts while expanding or shrinking the window efficiently.

Approach 1: Sorting and Two-Pointers (O(n log n) time, O(n) space)

This approach conceptually groups characters and uses a two-pointer style scan to maintain a valid segment where no character frequency exceeds two. After sorting auxiliary structures that track characters and indices, you move two pointers to maintain the longest valid span. When a character appears more than twice, shift the left pointer forward until the constraint is restored.

The core idea is similar to classic two pointers problems: expand the right pointer to include new characters and shrink the left pointer when constraints break. Sorting helps organize character occurrences but adds extra overhead. Time complexity is O(n log n) due to sorting, and space complexity is O(n) for auxiliary storage.

This method demonstrates the constraint-handling logic clearly but is rarely the optimal implementation because the substring is already sequential in the original string.

Approach 2: HashMap Sliding Window (O(n) time, O(1) space)

The optimal solution uses a sliding window combined with a frequency map. Maintain two pointers left and right that define the current substring. As you expand right, increment the count of s[right] in a hash table. If any character count exceeds two, move left forward while decrementing frequencies until the substring becomes valid again.

At every step, compute the window size right - left + 1 and update the maximum length. Each character enters and leaves the window at most once, which guarantees linear time. Because the alphabet size is bounded (typically lowercase English letters), the space complexity is effectively O(1).

This pattern appears frequently in substring problems where you enforce limits on character frequency. The sliding window ensures you never reprocess characters unnecessarily, making it both efficient and easy to implement.

Recommended for interviews: The sliding window with a hash map is the expected solution. Interviewers want to see that you recognize substring constraint problems and immediately apply the sliding window pattern. Explaining a brute-force idea or a less optimal pointer approach shows understanding, but implementing the O(n) window solution demonstrates strong problem-solving instincts.

Approach 1: Approach 1: Sorting and Two-Pointers

This approach leverages sorting and the two-pointer technique to solve the problem efficiently. By sorting the input initially, we can use two pointers to find the desired target without checking all possible pairs, which makes the solution more optimized compared to a brute force approach.

def find_pair(arr, target):
    arr.sort()
    left, right = 0, len(arr) - 1
    while left < right:
        current_sum = arr[left] + arr[right]
        if current_sum == target:
            print(f"Pair found ({arr[left]}, {arr[right]})")
            return
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    print("Pair not found")
import java.util.Arrays;

public class TwoSumSolution {
    public static void findPair(int[] arr, int target) {
        Arrays.sort(arr);
        int left = 0, right = arr.length - 1;
        while (left < right) {
            int sum = arr[left] + arr[right];
            if (sum == target) {
                System.out.println("Pair found (" + arr[left] + ", " + arr[right] + ")");
                return;
            } else if (sum < target) {
                left++;
            } else {
                right--;
            }
        }
        System.out.println("Pair not found");
    }
}
#include <iostream>
#include <vector>
#include <algorithm>

void findPair(std::vector<int>& arr, int target) {
    std::sort(arr.begin(), arr.end());
    int left = 0, right = arr.size() - 1;
    while (left < right) {
        int sum = arr[left] + arr[right];
        if (sum == target) {
            std::cout << "Pair found (" << arr[left] << ", " << arr[right] << ")\n";
            return;
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    std::cout << "Pair not found\n";
}
function findPair(arr, target) {
    arr.sort((a, b) => a - b);
    let left = 0;
    let right = arr.length - 1;
    while (left < right) {
        const sum = arr[left] + arr[right];
        if (sum === target) {
            console.log(`Pair found (${arr[left]}, ${arr[right]})`);
            return;
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    console.log("Pair not found");
}
#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

void findPair(int arr[], int n, int target) {
    qsort(arr, n, sizeof(int), compare);
    int left = 0, right = n - 1;
    while (left < right) {
        int sum = arr[left] + arr[right];
        if (sum == target) {
            printf("Pair found (%d, %d)\n", arr[left], arr[right]);
            return;
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    printf("Pair not found\n");
}
using System;

public class TwoSumSolution {
    public static void FindPair(int[] arr, int target) {
        Array.Sort(arr);
        int left = 0, right = arr.Length - 1;
        while (left < right) {
            int sum = arr[left] + arr[right];
            if (sum == target) {
                Console.WriteLine($"Pair found ({arr[left]}, {arr[right]})");
                return;
            } else if (sum < target) {
                left++;
            } else {
                right--;
            }
        }
        Console.WriteLine("Pair not found");
    }
}

The Python solution sorts the list with list.sort(). It uses a similar two-pointer approach to determine whether a pair that sums to the target exists, moving the pointers based on the sum's comparison to the target.

Complexity

Time Complexity: O(n log n) for sorting and O(n) for traversal, combining to O(n log n).
Space Complexity: O(1) for in-place operations.

Try this approach in the editor

Approach 2: Approach 2: HashMap (or HashSet for Some Languages)

This approach utilizes a hashmap to map from element to its index for efficient look-ups of complement values required to reach the target. The idea is to iterate through the array and check if the complement (target - current element) exists in the map, which can be achieved in constant time.

def find_pair(arr, target):
    seen_numbers = {}
    for num in arr:
        complement = target - num
        if complement in seen_numbers:
            print(f"Pair found ({complement}, {num})")
            return
        seen_numbers[num] = True
    print("Pair not found")
import java.util.HashMap;

public class TwoSumSolution {
    public static void findPair(int[] arr, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : arr) {
            int complement = target - num;
            if (map.containsKey(complement)) {
                System.out.println("Pair found (" + complement + ", " + num + ")");
                return;
            }
            map.put(num, 1);
        }
        System.out.println("Pair not found");
    }
}
#include <iostream>
#include <unordered_map>
#include <vector>

void findPair(std::vector<int>& arr, int target) {
    std::unordered_map<int, int> hashmap;
    for (auto num : arr) {
        int complement = target - num;
        if (hashmap.find(complement) != hashmap.end()) {
            std::cout << "Pair found (" << complement << ", " << num << ")\n";
            return;
        }
        hashmap[num] = 1;
    }
    std::cout << "Pair not found\n";
}
function findPair(arr, target) {
    const numSet = new Set();
    for (let num of arr) {
        const complement = target - num;
        if (numSet.has(complement)) {
            console.log(`Pair found (${complement}, ${num})`);
            return;
        }
        numSet.add(num);
    }
    console.log("Pair not found");
}
#include <stdio.h>
#include <stdlib.h>
#define MAX 100000

int hash[MAX] = {0};

void findPair(int arr[], int n, int target) {
    for (int i = 0; i < n; i++) {
        int complement = target - arr[i];
        if (complement >= 0 && hash[complement]) {
            printf("Pair found (%d, %d)\n", complement, arr[i]);
            return;
        }
        hash[arr[i]] = 1;
    }
    printf("Pair not found\n");
}
using System;
using System.Collections.Generic;

public class TwoSumSolution {
    public static void FindPair(int[] arr, int target) {
        var seenNumbers = new HashSet<int>();
        foreach (var num in arr) {
            int complement = target - num;
            if (seenNumbers.Contains(complement)) {
                Console.WriteLine($"Pair found ({complement}, {num})");
                return;
            }
            seenNumbers.Add(num);
        }
        Console.WriteLine("Pair not found");
    }
}

The Python implementation uses a dictionary to serve the purpose of a hashmap, allowing pair finding via direct checks for complementary numbers.

Complexity

Time Complexity: O(n) for linear traversal with constant time dictionary look-up.
Space Complexity: O(n) given the storage requirements of the dictionary.

Try this approach in the editor

Approach 3: Two Pointers

We use two pointers i and j to maintain a sliding window, and an array cnt to record the occurrence times of each character in the window.

In each iteration, we add the character c at the pointer j into the window, then check if cnt[c] is greater than 2. If it is, we move the pointer i to the right until cnt[c] is less than or equal to 2. At this point, we update the answer ans = max(ans, j - i + 1).

Finally, we return the answer ans.

The time complexity is O(n), where n is the length of the string s. The space complexity is O(|\Sigma|), where \Sigma is the character set, and in this problem, \Sigma = 26.

function maximumLengthSubstring(s: string): number {
    let ans = 0;
    const cnt: number[] = Array(26).fill(0);
    for (let i = 0, j = 0; j < s.length; ++j) {
        const idx = s[j].charCodeAt(0) - 'a'.charCodeAt(0);
        ++cnt[idx];
        while (cnt[idx] > 2) {
            --cnt[s[i++].charCodeAt(0) - 'a'.charCodeAt(0)];
        }
        ans = Math.max(ans, j - i + 1);
    }
    return ans;
}
func maximumLengthSubstring(s string) (ans int) {
	cnt := [26]int{}
	i := 0
	for j, c := range s {
		idx := c - 'a'
		cnt[idx]++
		for cnt[idx] > 2 {
			cnt[s[i]-'a']--
			i++
		}
		ans = max(ans, j-i+1)
	}
	return
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Sorting and Two-Pointers

Time Complexity: O(n log n) for sorting and O(n) for traversal, combining to O(n log n).
Space Complexity: O(1) for in-place operations.

Approach 2: HashMap (or HashSet for Some Languages)

Time Complexity: O(n) for linear traversal with constant time dictionary look-up.
Space Complexity: O(n) given the storage requirements of the dictionary.

Two Pointers–

Complexity analysis

ApproachTimeSpaceWhen to Use
Sorting and Two-PointersO(n log n)O(n)Useful for understanding constraint handling with pointer expansion and contraction, though not optimal for substring problems.
HashMap Sliding WindowO(n)O(1)Best choice for contiguous substring problems with frequency limits. Preferred in interviews and production code.

Frequently asked questions

Is Maximum Length Substring With Two Occurrences easy or hard?

LeetCode classifies this problem as Easy. The difficulty mainly lies in recognizing the sliding window pattern and correctly adjusting the left pointer when a character count exceeds two.

Maximum Length Substring With Two Occurrences Python/Java solution

Most implementations use the same sliding window logic across languages. Python typically uses a dictionary or collections.Counter, while Java uses HashMap or an int array for character counts. Both maintain two pointers and update frequencies while ensuring each character appears at most twice.

How to solve Maximum Length Substring With Two Occurrences in O(n)?

Use a sliding window with two pointers and a frequency map. Expand the right pointer while counting characters. If a character appears more than twice, move the left pointer forward and decrease counts until the window becomes valid again. Track the maximum window length during the scan.

What is the best approach for Maximum Length Substring With Two Occurrences?

The sliding window with a hash map is the most efficient approach. It maintains a dynamic window while tracking character frequencies and ensures no character appears more than twice. This method runs in O(n) time because each character is processed at most twice, once when expanding the window and once when shrinking it.

Is Maximum Length Substring With Two Occurrences asked at Google/Amazon/Meta?

Substring constraint problems using sliding window patterns frequently appear in interviews at companies like Amazon, Google, and Meta. Variants include limiting distinct characters, limiting frequency, or finding longest valid substrings under specific constraints.

What data structure is used in Maximum Length Substring With Two Occurrences?

The core data structure is a hash map (or fixed-size frequency array) to store counts of characters inside the current window. This structure allows constant-time updates and checks while the sliding window expands and shrinks.

What is the time complexity of Maximum Length Substring With Two Occurrences?

The optimal sliding window solution runs in O(n) time where n is the length of the string. Each character is added to the window once and removed at most once. Space complexity is O(1) because the frequency map only stores counts for a limited set of characters.

Comments

Now write it yourselfClose this page and solve Maximum Length Substring With Two Occurrences in the editor, without looking.
Practise Maximum Length Substring With Two Occurrences