Skip to content

Latest commit

 

History

History

0927.Three Equal Parts

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

English Version

题目描述

给定一个由 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

解法

方法一:计数 + 三指针

我们记数组的长度为 $n$,数组中 $1$ 的数量为 $cnt$

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

我们将 $cnt$ 除以 $3$,得到每一份中 $1$ 的数量,然后找到每一份的第一个 $1$ 在数组 arr 中的位置(参考以下代码中的 $find(x)$ 函数),分别记为 $i$, $j$, $k$

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

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

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

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

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

相似题目:

Python3

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]

Java

class Solution {
    private int[] arr;

    public int[] threeEqualParts(int[] arr) {
        this.arr = arr;
        int cnt = 0;
        int n = arr.length;
        for (int v : arr) {
            cnt += v;
        }
        if (cnt % 3 != 0) {
            return new int[] {-1, -1};
        }
        if (cnt == 0) {
            return new int[] {0, n - 1};
        }
        cnt /= 3;

        int i = find(1), j = find(cnt + 1), k = find(cnt * 2 + 1);
        for (; k < n && arr[i] == arr[j] && arr[j] == arr[k]; ++i, ++j, ++k) {
        }
        return k == n ? new int[] {i - 1, j} : new int[] {-1, -1};
    }

    private int find(int x) {
        int s = 0;
        for (int i = 0; i < arr.length; ++i) {
            s += arr[i];
            if (s == x) {
                return i;
            }
        }
        return 0;
    }
}

C++

class Solution {
public:
    vector<int> threeEqualParts(vector<int>& arr) {
        int n = arr.size();
        int cnt = accumulate(arr.begin(), arr.end(), 0);
        if (cnt % 3) return {-1, -1};
        if (!cnt) return {0, n - 1};
        cnt /= 3;

        auto find = [&](int x) {
            int s = 0;
            for (int i = 0; i < n; ++i) {
                s += arr[i];
                if (s == x) return i;
            }
            return 0;
        };
        int i = find(1), j = find(cnt + 1), k = find(cnt * 2 + 1);
        for (; k < n && arr[i] == arr[j] && arr[j] == arr[k]; ++i, ++j, ++k) {}
        return k == n ? vector<int>{i - 1, j} : vector<int>{-1, -1};
    }
};

Go

func threeEqualParts(arr []int) []int {
	find := func(x int) int {
		s := 0
		for i, v := range arr {
			s += v
			if s == x {
				return i
			}
		}
		return 0
	}
	n := len(arr)
	cnt := 0
	for _, v := range arr {
		cnt += v
	}
	if cnt%3 != 0 {
		return []int{-1, -1}
	}
	if cnt == 0 {
		return []int{0, n - 1}
	}
	cnt /= 3
	i, j, k := find(1), find(cnt+1), find(cnt*2+1)
	for ; k < n && arr[i] == arr[j] && arr[j] == arr[k]; i, j, k = i+1, j+1, k+1 {
	}
	if k == n {
		return []int{i - 1, j}
	}
	return []int{-1, -1}
}

JavaScript

/**
 * @param {number[]} arr
 * @return {number[]}
 */
var threeEqualParts = function (arr) {
    function find(x) {
        let s = 0;
        for (let i = 0; i < n; ++i) {
            s += arr[i];
            if (s == x) {
                return i;
            }
        }
        return 0;
    }
    const n = arr.length;
    let cnt = 0;
    for (const v of arr) {
        cnt += v;
    }
    if (cnt % 3) {
        return [-1, -1];
    }
    if (cnt == 0) {
        return [0, n - 1];
    }
    cnt = Math.floor(cnt / 3);
    let [i, j, k] = [find(1), find(cnt + 1), find(cnt * 2 + 1)];
    for (; k < n && arr[i] == arr[j] && arr[j] == arr[k]; ++i, ++j, ++k) {}
    return k == n ? [i - 1, j] : [-1, -1];
};

...