Leetcode 927. 三等分

给定一个由 0 和 1 组成的数组 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 * 10^4
arr[i] 是 0 或 1

1.先判断1的个数。
如果个数为0,直接返回[0,2];
如果个数不为0,判断个数能否被3整除,如果不能整除的话返回[-1, -1]。

2.当个数能被3整除时,算出个数/3,即为每部分1的个数。
能确定的是,第三部分的值,即第三部分第一个1后的数字是确定的。

例如:
0 1 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0
按着1的个数分成3份,根据第三部分确定下来值为1100。
0 - 1 1 0 0 0 - 1 1 0 0 0 0 0 - 1 1 0 0

3.将横杠这个向右移
0 1 - 1 0 0 0 1 - 1 0 0 0 0 0 1 - 1 0 0
0 1 1 - 0 0 0 1 1 - 0 0 0 0 0 1 1 - 0 0
0 1 1 0 - 0 0 1 1 0 - 0 0 0 0 1 1 0 - 0
0 1 1 0 0 - 0 1 1 0 0 - 0 0 0 1 1 0 0
就得出结果了。

我写的,哈哈,逗乐了:

#Python3
class Solution:
    def threeEqualParts(self, arr: List[int]) -> List[int]:
        onenum = arr.count(1)
        if onenum == 0:
            return [0, 2]
        elif onenum % 3 != 0:
            return [-1, -1]
        someone = onenum // 3
        first = second = third = 0
        i = len(arr)

        while i :
            i -= 1
            if arr[i] == 1:
                third += 1
                if third == someone :
                    third = i
                    break
        print("third", third)
        while i :
            i -= 1
            if arr[i] == 1:
                second += 1
                if second == someone :
                    second = i
                    break
        print("second", second)
        while i :
            i -= 1
            if arr[i] == 1:
                first += 1
                if first == someone :
                    first = i
                    break
        
        while third < len(arr) and arr[first] == arr[second] == arr[third]:
            first, second, third = first + 1, second + 1, third + 1
        if third == len(arr) :
            return [first - 1, second] 
        else :
            return [-1, -1]


        return [i, j]

看的这个哥们的题解,理解贼快:
作者:lcbin
链接:https://leetcode.cn/problems/three-equal-parts/solution/by-lcbin-7ir1/
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]

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};
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个只包含正整数的非空数组,是否可以将这个数组分成两个子集,使得两个子集的元素和相等。 示例: 输入:[1, 5, 11, 5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11]。 解题思路: 这是一道经典的 0-1 背包问题,可以使用动态规划或者回溯算法解决。 使用回溯算法,需要定义一个 backtrack 函数,该函数有三个参数: - 数组 nums; - 当前处理到的数组下标 index; - 当前已经选择的元素和 leftSum。 回溯过程中,如果 leftSum 等于数组元素和的一半,那么就可以直接返回 true。如果 leftSum 大于数组元素和的一半,那么就可以直接返回 false。如果 index 到达数组末尾,那么就可以直接返回 false。 否则,就对于当前元素,有选择和不选择两种情况。如果选择当前元素,那么 leftSum 就加上当前元素的值,index 就加 1。如果不选择当前元素,那么 leftSum 不变,index 也加 1。最终返回所有可能性的结果中是否有 true。 Java 代码实现: class Solution { public boolean canPartition(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } if (sum % 2 != 0) { return false; } Arrays.sort(nums); return backtrack(nums, nums.length - 1, sum / 2); } private boolean backtrack(int[] nums, int index, int leftSum) { if (leftSum == 0) { return true; } if (leftSum < 0 || index < 0 || leftSum < nums[index]) { return false; } return backtrack(nums, index - 1, leftSum - nums[index]) || backtrack(nums, index - 1, leftSum); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值