↓Skip to main content
  1. LeetCode/

LeetCode 927: Three Equal Parts

·3 mins· ·
LeetCode Hard Math Array
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2025-07-16

  • Submissions: 18 (many WA / RE → AC on the morning of 2025-07-17 → 7 more failures in a rewrite → AC)

Approach
#

Leading zeros do not change the value, so the three parts represent one binary number ⇔ they are identical after stripping leading zeros.

  1. Every part has the same number of 1s: if the total is not divisible by 3, it is impossible.
  2. All zeros: every split gives 0, so return [0, n - 1].
  3. Each part has k = total ones / 3 ones. Find the positions a, b, c of the 1st, (k + 1)-th and (2k + 1)-th ones: the starts of the three parts after stripping leading zeros.
  4. The third part always extends to the end, owning the trailing zeros, so every part’s length from its first 1 is L = n - c.
  5. Check that arr[a:a+L], arr[b:b+L] and arr[c:] match, that part one ends before part two starts (a + L <= b), and part two before part three (b + L <= c).
  6. The answer is [a + L - 1, b + L].

My Attempts
#

This took 18 submissions. The first 9 scanned right to left accumulating each part’s value with 2 ** (position), and the boundaries kept breaking:

  • All zeros were not handled: [0, 0, 0] raised IndexError (res was empty) or returned [-1, -1], while the answer is [0, 2]. One version even special-cased if arr == [0, 0, 0, 0, 0]: return [0, 4] to get past a specific test.
  • The first AC returned [0, n - 1] when part_count == 0.

The same morning I rewrote it as “take the third part as a template, then match leftward”, and kept getting the template position and the returned indices off by one, 7 more failures. For instance [1, 1, 1] returned [0, 1] (the answer is [0, 2]) and [1, 1, 1, 1, 1, 1] returned [1, 3] (the answer is [1, 4]).

The solution above compares directly from the three positions a, b, c, with no values to compute and fewer chances to be off by one.

Solution
#

class Solution:
    def threeEqualParts(self, arr: List[int]) -> List[int]:
        n = len(arr)
        ones = sum(arr)
        if ones == 0:
            return [0, n - 1]                      # all zeros
        if ones % 3:
            return [-1, -1]
        k = ones // 3

        starts = []                                # positions of the 1st, (k+1)-th, (2k+1)-th ones
        seen = 0
        for i, x in enumerate(arr):
            if x:
                if seen % k == 0:
                    starts.append(i)
                seen += 1
        a, b, c = starts
        L = n - c                                  # the third part runs to the end and fixes the length

        if a + L <= b and b + L <= c and arr[a:a + L] == arr[b:b + L] == arr[c:]:
            return [a + L - 1, b + L]
        return [-1, -1]

Complexity
#

Time O(n), space O(n) for the slices (three pointers comparing digit by digit make it O(1)).

Mistakes to Avoid
#

  • The all-zeros case.
  • Computing values with 2 ** position: with up to 3 × 10^4 digits the numbers are huge, and off-by-ones creep in.
  • The returned j is where the third part starts, not where the second ends.

Interview Explanation
#

Leading zeros do not matter, so the parts must match after stripping them. I count the 1s: not divisible by 3 is impossible, all zeros splits anywhere. Then I find each part’s first 1; the third part runs to the end, so its length fixes how much each part must match, and if the three match without overlapping, the cut points follow. Time O(n).

Related

LeetCode 952: Largest Component Size by Common Factor
·2 mins
LeetCode Hard Math Number-Theory Union-Find Hash-Table Array
LeetCode 952 note: sharing a factor ⇔ sharing a prime factor; factor each number and union indices with the same prime factor using Union-Find, with no pairwise GCDs
LeetCode 3518: Smallest Palindromic Rearrangement II
·3 mins
LeetCode Hard Math Combinatorics Counting Hash-Table String
LeetCode 3518 note: a palindrome is determined by its left half, so this is the k-th permutation of a multiset; try characters position by position and use permutation counts, updated in O(1), to find k’s branch
LeetCode 1814: Count Nice Pairs in an Array
·1 min
LeetCode Medium Array Hash-Table Math Counting
LeetCode 1814 note: rearrange the condition into nums[i] - rev(nums[i]) == nums[j] - rev(nums[j]), count pairs per value, and remember the modulus
LeetCode 313: Super Ugly Number
·2 mins
LeetCode Medium Array Math Dynamic-Programming
LeetCode 313 note: generalizing LC 264 with one pointer per prime; with a heap, avoid pushing the same number many times
LeetCode 396: Rotate Function
·2 mins
LeetCode Medium Array Math Dynamic-Programming
LeetCode 396 note: F(k) and F(k - 1) differ by one formula: F(k) = F(k - 1) + sum - n × the element moved to the front
LeetCode 189: Rotate Array
·2 mins
LeetCode Medium Array Math Two-Pointers
LeetCode 189 note: take k %= n, then reverse three times: the whole array, the first k, and the last n - k, with O(1) extra space