LeetCode 题解工作台

三等分

给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分 ,使得所有这些部分表示相同的二进制值。 如果可以做到,请返回 任何 [i, j] ,其中 i+1 ,这样一来: arr[0], arr[1], ..., arr[i] 为第一部分; arr[i + 1], arr[i + 2…

category

2

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 数组·数学

bolt

答案摘要

我们记数组的长度为 ,数组中 的数量为 。 显然 必须是 的倍数,否则无法将数组三等分,可以提前返回 $[-1, -1]$。如果 为 ,那么意味着数组中所有元素都为 ,直接返回 $[0, n - 1]$ 即可。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数组·数学 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给定一个由 01 组成的数组 arr ,将数组分成  3 个非空的部分 ,使得所有这些部分表示相同的二进制值。

如果可以做到,请返回任何 [i, j],其中 i+1 < j,这样一来:

  • arr[0], arr[1], ..., arr[i] 为第一部分;
  • arr[i + 1], arr[i + 2], ..., arr[j - 1] 为第二部分;
  • arr[j], arr[j + 1], ..., arr[arr.length - 1] 为第三部分。
  • 这三个部分所表示的二进制值相等。

如果无法做到,就返回 [-1, -1]

注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的,所以 [0,1,1] 和 [1,1] 表示相同的值。

 

示例 1:

输入:arr = [1,0,1,0,1]
输出:[0,3]

示例 2:

输入:arr = [1,1,0,1,1]
输出:[-1,-1]

示例 3:

输入:arr = [1,1,0,0,1]
输出:[0,2]

 

提示:

  • 3 <= arr.length <= 3 * 104
  • arr[i] 是 0 或 1
lightbulb

解题思路

方法一:计数 + 三指针

我们记数组的长度为 nn,数组中 11 的数量为 cntcnt

显然 cntcnt 必须是 33 的倍数,否则无法将数组三等分,可以提前返回 [1,1][-1, -1]。如果 cntcnt00,那么意味着数组中所有元素都为 00,直接返回 [0,n1][0, n - 1] 即可。

我们将 cntcnt 除以 33,得到每一份中 11 的数量,然后找到每一份的第一个 11 在数组 arr 中的位置(参考以下代码中的 find(x)find(x) 函数),分别记为 ii, jj, kk

0 1 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0
  ^         ^             ^
  i         j             k

接着我们从 ii, jj, kk 开始往后同时遍历每一部分,判断三部分对应的值是否相等,是则继续遍历,直至 kk 到达 arrarr 末尾。

0 1 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0
          ^         ^             ^
          i         j             k

遍历结束时,若 k=nk=n,说明满足三等分,返回此时的 [i1,j][i - 1, j] 作为答案,否则返回 [1,1][-1, -1]

时间复杂度 O(n)O(n),其中 nn 表示 arr 的长度。空间复杂度 O(1)O(1)

相似题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def threeEqualParts(self, arr: List[int]) -> List[int]:
        def find(x):
            s = 0
            for i, v in enumerate(arr):
                s += v
                if s == x:
                    return i

        n = len(arr)
        cnt, mod = divmod(sum(arr), 3)
        if mod:
            return [-1, -1]
        if cnt == 0:
            return [0, n - 1]

        i, j, k = find(1), find(cnt + 1), find(cnt * 2 + 1)
        while k < n and arr[i] == arr[j] == arr[k]:
            i, j, k = i + 1, j + 1, k + 1
        return [i - 1, j] if k == n else [-1, -1]
speed

复杂度分析

指标
时间complexity is O(n) for single-pass counting and alignment checks, where n is the length of the array. Space complexity is O(1) additional memory if segments are compared via indices without extra arrays.
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Checking if total ones count is divisible by three is crucial.

  • question_mark

    Careful handling of leading zeros distinguishes correct from incorrect partitions.

  • question_mark

    Aligning segments from the last one backwards helps validate equality efficiently.

warning

常见陷阱

外企场景
  • error

    Assuming leading zeros affect integer comparison, which can cause wrong splits.

  • error

    Forgetting to handle arrays with zero ones as a valid equal split.

  • error

    Incorrectly computing indices when trailing zeros are required for alignment.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Partition a binary array into k equal-value parts instead of three, requiring generalization of ones distribution.

  • arrow_right_alt

    Find the minimal length of the first part to achieve three equal binary values for optimization problems.

  • arrow_right_alt

    Allowing arrays with non-binary integers and defining equality via decimal value rather than binary string comparison.

help

常见问题

外企场景

三等分题解:数组·数学 | LeetCode #927 困难