【927. 三等分】
来源:力扣(LeetCode)
描述:
给定一个由 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 * 104
- arr[i] 是 0 或 1
方法 :将 1 的数量三等分
思路与算法
如果存在一种分法使得三个非空部分所表示的二进制值相同,那么最终每一部分 1 的数量一定是相等的。根据这个思想,我们首先统计数组 arr 中 1 的个数,把它设为 sum。如果 sum 不能被 3 整除,那么显然不存在正确分法。否则,每一个部分都应当有 partial = sum / 3 个 1。
我们尝试找到 arr 中第 1 个 1 出现的位置 first,第 partial + 1 个 1 出现的位置 second 以及第 2 × partial + 1 个 1 出现的位置 third。因为每一部分末尾的 0 可以移动到下一部分的首部从而改变二进制值的大小, 所以每一部分的末尾难以界定。但是注意到,数组的末尾是无法改变的,因此区间 [third, arr.length − 1] 所表示的二进制值可以固定。
设 len = arr.length − third,表示二进制值的长度。接下来只需要判断 [first, first + len)、 [second, second + len) 和 [third, third + len) 是否完全相同即可。前提是 first + len ≤ second 并且 second + len ≤ third。
如果以上三段区间是完全相同的,那么答案就是 [first + len − 1, second + len]。最后需要注意到,如果 sum = 0,我们需要直接返回答案 [0, 2](或者其他任意合法答案)。
代码:
class Solution {public:vector<int> threeEqualParts(vector<int>& arr) {int sum = accumulate(arr.begin(), arr.end(), 0);if (sum % 3 != 0) {return {-1, -1};}if (sum == 0) {return {0, 2};}int partial = sum / 3;int first = 0, second = 0, third = 0, cur = 0;for (int i = 0; i < arr.size(); i++) {if (arr[i] == 1) {if (cur == 0) {first = i;}else if (cur == partial) {second = i;}else if (cur == 2 * partial) {third = i;}cur++;}}int len = (int)arr.size() - third;if (first + len <= second && second + len <= third) {int i = 0;while (third + i < arr.size()) {if (arr[first + i] != arr[second + i] || arr[first + i] != arr[third + i]) {return {-1, -1};}i++;}return {first + len - 1, second + len};}return {-1, -1};}
};
执行用时:24 ms, 在所有 C++ 提交中击败了98.26%的用户
内存消耗:37.9 MB, 在所有 C++ 提交中击败了79.86%的用户
复杂度分析
时间复杂度: O(n),其中 n 是 arr 的长度。找到三个下标的时间复杂度为 O(n),判断三个部分是否相同的时间复杂度也是 O(n)。
空间复杂度: O(1),只用到常数个变量空间。
author:LeetCode-Solution
【927. 三等分】相关推荐
- LeetCode每日一题——927. 三等分
LeetCode每日一题系列 题目:927. 三等分 难度:困难 文章目录 LeetCode每日一题系列 题目 示例 思路 题解 题目 给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个 ...
- LeetCode每日一题:927. 三等分 (困难) 数组 数学
题目:力扣 给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分 ,使得所有这些部分表示相同的二进制值. 如果可以做到,请返回任何 [i, j],其中 i+1 < j,这 ...
- leetcode 927. Three Equal Parts | 927. 三等分(Java)
题目 https://leetcode.com/problems/three-equal-parts/ 题解 不知道为什么是 hard,感觉这道题没有套路(印象中这几道 hard 都没有什么套路,这就 ...
- 如何学好C语言--你的学渣朋友告诉你
光说不练假把式,光练不说傻把式,又练又说真把式. 真实感受,不是我不想学,是我真的不知道我哪里不会啊和得怎么做啊?本文作者当初就是这么废掉的 推荐两个练习的网站 (一)C语言网 https://www ...
- LeetCode题解汇总
题目 推荐指数 1. 两数之和 1 2. 两数相加 1 4. 寻找两个正序数组的中位数 2AAAA 6. Z 字形变换 1 7. 整数反转 2 8. 字符串转换整数 (atoi) 2AAA 9. 回文 ...
- 算法学习-数组的相关操作,简单的数据结构逆天的难度,扮猪吃老虎(持续更新中)
文章目录 相关知识 Java中Arrays常用api 相关题目 26.删除有序数组中的重复项 80.删除有序数组中的重复项II 66.加一 75.颜色分类 268.丢失的数字 448.找到所有数组中消 ...
- leetcode 转载
转载: https://blog.csdn.net/love905661433/article/details/84980135 LeetCode 1- 100 1. 两数之和 : https://b ...
- 字节跳动2021年4月面试算法题库
本文汇总了牛客2021.4.1~2021.4.30 面经考到的Leetcode题目 最终的高频题榜单数据可以在CodeTop题库(https://codetop.cc)查询,支持按部门.岗位分类筛选. ...
- 【Leetcode】每日一题打卡(64)
1619. 删除某些元素后的数组均值 - 简单ac class Solution { public:double trimMean(vector<int>& arr) {sort( ...
最新文章
- python的基础网络编程是下列_Python基础(六)网络编程
- htmlunit爬虫工具使用--模拟浏览器发送请求,获取JS动态生成的页面内容
- 跳表(SkipList)设计与实现(java)
- fmt.Println、fmt.Printf、fmt.Sprintf、fmt.Sprintln
- Soring冲刺计划第三天(个人)
- SFB 项目经验-02-共存迁移-Lync 2013-TO-SFB 2015-规划02
- C#循环给多个控件赋值
- 01-hibernate注解:类级别注解,@Entity,@Table,@Embeddable
- java执行数学表达式_数学表达式解析-JAVA版
- Webpack入门教程二
- Ubuntu学习日记--Lesson10:gcc、make、makefile、cmake、cmakelists区别
- kafka传数据到Flink存储到mysql之Flink使用SQL语句聚合数据流(设置时间窗口,EventTime)...
- 2022级sdut知到/智慧树---c语言第一章测试题解
- 苹果7系统更新12无服务器,别再为苹果手机无法更新系统犯难,这几种方式帮你解决!...
- 树莓派引脚介绍与GPIO的初步认识与应用
- Visio中画各种线条与箭头
- 学计算机应用技术买什么笔记本电脑,大学什么专业用电脑 要不要买电脑
- JavaScript数组扁平化
- 基于JAVA家电售后管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
- 如何改变视频的MD5值?一分钟让你学会操作