Facebook Pixel

3696. Maximum Distance Between Unequal Words in Array I 🔒

EasyArrayString
LeetCode ↗

Problem Description

You are given a string array words.

Your task is to find the maximum distance between two distinct indices i and j that satisfy the following condition:

  • words[i] != words[j] — the words at these two indices must be different.

The distance between indices i and j is defined as j - i + 1, which is essentially the length of the subarray spanning from index i to index j (inclusive).

Return the maximum distance among all such valid pairs. If no valid pair exists (meaning all words in the array are identical), return 0.

Example:

Suppose words = ["a", "b", "a", "a"]:

  • The pair (i = 0, j = 1) is valid since "a" != "b", giving a distance of 1 - 0 + 1 = 2.
  • The pair (i = 1, j = 3) is valid since "b" != "a", giving a distance of 3 - 1 + 1 = 3.

The maximum distance is 3.

If words = ["a", "a", "a"], every pair of words is identical, so no valid pair exists and the answer is 0.

Key points to keep in mind:

  1. The two indices must point to different words — comparing a word with an identical copy of itself does not count.
  2. The distance formula j - i + 1 means a pair of adjacent differing words already yields a distance of 2.
  3. To maximize the distance, you want the two differing words to be as far apart as possible, ideally near the two ends of the array.
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

How We Pick the Algorithm

Why Two pointers?

This problem maps to Two pointers through a short path in the full flowchart.

Tree orgraph?noTwopointers /findyesTwo pointers

The optimal pair must anchor at either index 0 or n-1, reducing the search to comparing each word against both endpoints in one pass.

Open in Flowchart

Intuition

A brute-force approach would check every pair (i, j) and track the maximum j - i + 1, but that takes O(n^2) time. To do better, we need a key observation about where the optimal pair must be located.

Since we want to maximize j - i + 1, we naturally want i to be as small as possible and j to be as large as possible. The extreme case is i = 0 and j = n - 1, giving a distance of n. This leads us to ask: does the optimal pair always involve one of the two endpoints of the array?

The answer is yes, and we can see why through a proof by contradiction:

  • Suppose the optimal pair is (i, j) where neither index is an endpoint, i.e., 0 < i and j < n - 1.
  • If words[0] != words[j], then the pair (0, j) would be valid and have a larger distance than (i, j) — contradicting that (i, j) is optimal. So it must be that words[0] == words[j].
  • Similarly, if words[i] != words[n - 1], the pair (i, n - 1) would be larger. So it must be that words[i] == words[n - 1].
  • But now look at the endpoints themselves: words[0] == words[j] and words[n - 1] == words[i], and we know words[i] != words[j]. This forces words[0] != words[n - 1], making (0, n - 1) a valid pair with distance n — strictly larger than j - i + 1. Contradiction again.

Therefore, at least one element of the optimal pair must sit at index 0 or index n - 1.

This insight collapses the problem dramatically: instead of checking all pairs, we only need to compare every word against the first word and the last word:

  • If words[i] != words[0], the pair (0, i) gives distance i + 1.
  • If words[i] != words[n - 1], the pair (i, n - 1) gives distance n - i.

Taking the maximum over all such candidates yields the answer in a single O(n) pass with O(1) extra space. If no word differs from either endpoint, all words are identical, and the answer naturally stays at 0.

Solution Approach

Based on the insight that the optimal pair must include either the first or the last element, we use a single-pass scan that compares every word against the two endpoints of the array.

Step-by-Step Walkthrough

Step 1 — Setup

Record the array length n and initialize the answer:

n = len(words)
ans = 0

Starting ans at 0 handles the edge case where all words are identical — no comparison will ever update it, so 0 is returned as required.

Step 2 — Scan and compare against both endpoints

For each index i from 0 to n - 1, perform two checks:

for i in range(n):
    if words[i] != words[0]:
        ans = max(ans, i + 1)
    if words[i] != words[-1]:
        ans = max(ans, n - i)
  • Check against the first word: If words[i] != words[0], then (0, i) is a valid pair. Its distance is i - 0 + 1 = i + 1.
  • Check against the last word: If words[i] != words[-1], then (i, n - 1) is a valid pair. Its distance is (n - 1) - i + 1 = n - i.

Each valid candidate updates ans via max.

Step 3 — Return the result

return ans

Why This Covers All Cases

From the proof in the intuition, every optimal pair must anchor at index 0 or index n - 1. The loop exhaustively enumerates:

  • All pairs of the form (0, i) — covered by the first check.
  • All pairs of the form (i, n - 1) — covered by the second check.

The special pair (0, n - 1) is covered by both checks (when i = n - 1 in the first check, or i = 0 in the second), so no candidate is missed.

Trace Example

Take words = ["a", "b", "a", "a"], so n = 4:

iwords[i]vs words[0] = "a"vs words[-1] = "a"ans
0"a"equal — skipequal — skip0
1"b"differ → i + 1 = 2differ → n - i = 33
2"a"equal — skipequal — skip3
3"a"equal — skipequal — skip3

Final answer: 3, matching the pair (1, 3).

Complete Code

class Solution:
    def maxDistance(self, words: List[str]) -> int:
        n = len(words)
        ans = 0
        for i in range(n):
            if words[i] != words[0]:
                ans = max(ans, i + 1)
            if words[i] != words[-1]:
                ans = max(ans, n - i)
        return ans

Complexity Analysis

  • Time Complexity: O(n × m), where n is the number of words and m is the average word length — each of the n iterations performs two string comparisons costing up to O(m). If string comparison is treated as O(1), this is simply O(n).
  • Space Complexity: O(1) — only the variables n and ans are used; no auxiliary data structures are needed.

Example Walkthrough

Let's trace the algorithm with words = ["a", "b", "a", "b", "a"], where n = 5.

Here the first word is words[0] = "a" and the last word is words[-1] = "a". Notice the two endpoints are identical, so the trivial pair (0, 4) with distance 5 is not valid — the answer must come from an inner element paired with one of the endpoints.

We initialize ans = 0 and scan each index, comparing against both endpoints:

iwords[i]vs words[0] = "a"vs words[-1] = "a"ans
0"a"equal — skipequal — skip0
1"b"differ → pair (0, 1), distance i + 1 = 2differ → pair (1, 4), distance n - i = 44
2"a"equal — skipequal — skip4
3"b"differ → pair (0, 3), distance i + 1 = 4differ → pair (3, 4), distance n - i = 24
4"a"equal — skipequal — skip4

Step-by-step highlights:

  • At i = 1, the word "b" differs from both endpoints. Anchoring at the first word gives the pair (0, 1) with distance 2, but anchoring at the last word gives the much better pair (1, 4) with distance 5 - 1 = 4. The answer jumps to 4.
  • At i = 3, "b" again differs from both endpoints. This time the first-word anchor is the stronger candidate: pair (0, 3) yields distance 3 + 1 = 4. It ties the current best, so ans remains 4.
  • Indices 0, 2, and 4 hold "a", matching both endpoints, so they contribute nothing.

Final answer: 4, achieved by either (1, 4) — "b" vs "a" — or (0, 3) — "a" vs "b".

This example illustrates the core insight nicely: even though the global endpoints (0, 4) form an invalid pair (both are "a"), the optimal valid pair still anchors at one of the two endpoints, which is exactly why a single pass comparing each word against words[0] and words[-1] suffices.

Solution Implementation

1class Solution:
2    def maxDistance(self, words: List[str]) -> int:
3        # Total number of words in the list
4        num_words = len(words)
5        # Maximum distance found so far
6        max_dist = 0
7
8        for i in range(num_words):
9            # If the current word differs from the first word,
10            # the distance between index 0 and index i is (i - 0 + 1)
11            if words[i] != words[0]:
12                max_dist = max(max_dist, i + 1)
13
14            # If the current word differs from the last word,
15            # the distance between index i and the last index is (n - 1 - i + 1)
16            if words[i] != words[-1]:
17                max_dist = max(max_dist, num_words - i)
18
19        return max_dist
20
1class Solution {
2    public int maxDistance(String[] words) {
3        // Total number of words in the array
4        int wordCount = words.length;
5        // Stores the maximum distance found so far
6        int maxDist = 0;
7
8        // Iterate through every word in the array
9        for (int index = 0; index < wordCount; ++index) {
10            // If the current word differs from the first word,
11            // the distance between them is (index - 0 + 1) = index + 1
12            if (!words[index].equals(words[0])) {
13                maxDist = Math.max(maxDist, index + 1);
14            }
15            // If the current word differs from the last word,
16            // the distance between them is (wordCount - 1 - index + 1) = wordCount - index
17            if (!words[index].equals(words[wordCount - 1])) {
18                maxDist = Math.max(maxDist, wordCount - index);
19            }
20        }
21
22        // Return the maximum distance between two distinct words
23        return maxDist;
24    }
25}
26
1class Solution {
2public:
3    int maxDistance(vector<string>& words) {
4        int size = words.size();
5        int maxDist = 0;
6
7        for (int i = 0; i < size; ++i) {
8            // If the current word differs from the first word,
9            // the distance between index 0 and index i is (i + 1).
10            if (words[i] != words[0]) {
11                maxDist = max(maxDist, i + 1);
12            }
13
14            // If the current word differs from the last word,
15            // the distance between index i and index (size - 1) is (size - i).
16            if (words[i] != words[size - 1]) {
17                maxDist = max(maxDist, size - i);
18            }
19        }
20
21        return maxDist;
22    }
23};
24
1/**
2 * Finds the maximum distance between two indices i and j
3 * such that words[i] !== words[j].
4 *
5 * Key insight: one of the optimal endpoints must be either
6 * the first word or the last word of the array. So we only
7 * need to compare each word against words[0] and words[n - 1].
8 *
9 * Time complexity:  O(n) — single pass through the array
10 * Space complexity: O(1) — only constant extra variables
11 *
12 * @param words - the input array of strings
13 * @returns the maximum distance (j - i + 1) between two different words,
14 *          or 0 if all words are identical
15 */
16function maxDistance(words: string[]): number {
17    const n: number = words.length;
18    let ans: number = 0;
19
20    for (let i = 0; i < n; i++) {
21        // If the current word differs from the first word,
22        // the distance from index 0 to index i is (i + 1).
23        if (words[i] !== words[0]) {
24            ans = Math.max(ans, i + 1);
25        }
26
27        // If the current word differs from the last word,
28        // the distance from index i to index (n - 1) is (n - i).
29        if (words[i] !== words[n - 1]) {
30            ans = Math.max(ans, n - i);
31        }
32    }
33
34    return ans;
35}
36

Time and Space Complexity

  • Time Complexity: O(n), where n is the length of the array words. The code iterates through the array exactly once with a single for loop. In each iteration, it performs a constant number of operations: two string comparisons (words[i] != words[0] and words[i] != words[-1]) and at most two max updates on ans. Since each iteration costs O(1) and there are n iterations, the overall time complexity is O(n).

  • Space Complexity: O(1). The algorithm only uses a fixed number of extra variables (n, ans, and the loop index i), regardless of the input size. No additional data structures are allocated, so the extra space used is constant.

Pattern Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Using j - i Instead of j - i + 1 as the Distance

A frequent off-by-one mistake is treating the distance as the gap between indices rather than the length of the subarray:

# WRONG: computes j - i instead of j - i + 1
for i in range(n):
    if words[i] != words[0]:
        max_dist = max(max_dist, i)          # should be i + 1
    if words[i] != words[-1]:
        max_dist = max(max_dist, n - i - 1)  # should be n - i

For words = ["a", "b"], this returns 1 instead of the correct 2. The problem defines distance as j - i + 1 (inclusive length), so two adjacent differing words already produce a distance of 2, not 1.

Solution: Carefully translate the formula. The pair (0, i) has distance i - 0 + 1 = i + 1, and the pair (i, n - 1) has distance (n - 1) - i + 1 = n - i. A quick sanity check with a two-element array like ["a", "b"] (expected output 2) immediately exposes this bug.


Pitfall 2: Breaking Out of the Loop Too Early

It is tempting to "optimize" by stopping at the first mismatch:

# WRONG: early exit misses the better anchor
for i in range(n):
    if words[i] != words[0]:
        return i + 1   # exits before checking the last-word anchor

For words = ["a", "b", "a", "a"], this returns 2 (pair (0, 1)), missing the optimal answer 3 from pair (1, 3). The first mismatch against words[0] is not necessarily part of the maximum-distance pair — the optimal pair may anchor at the last element instead.

Solution: Either scan the full array updating max(ans, ...) for both anchors (as the provided code does), or use the two-pointer variant correctly: scan forward to find the first index differing from words[-1] (candidate n - i), and scan backward to find the last index differing from words[0] (candidate j + 1), then take the maximum of the two. Both anchors must always be considered before returning.


Pitfall 3: Comparing Only words[0] and words[-1] and Returning Early

Another shortcut that fails is assuming that if the two endpoints differ you are done, and if they are equal the answer is 0:

# WRONG: only handles one special case
if words[0] != words[-1]:
    return n
return 0   # incorrect — interior elements may still differ from the endpoints

For words = ["a", "b", "a"], the endpoints are equal, but the pair (0, 1) or (1, 2) gives a valid distance of 2. The correct insight is that the optimal pair must include one endpoint — not that it must consist of both endpoints.

Solution: Keep the early return for words[0] != words[-1] (returning n is valid there as it is the maximum possible distance), but when the endpoints are equal, you must still scan the interior elements against the endpoints, exactly as the full loop does.

Ready to land your dream job?

Unlock your dream job with a 5-minute quiz for a personalized study roadmap!

Get My Roadmap
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Get a Personalized Study Roadmap:

Which data structure is used in a depth first search?


Recommended Readings

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

Load More