本文涉及知识点
数学
LeetCode927. 三等分
给定一个由 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,直接返回{0,arr.size()-1}
我们将二进制数分为三部分:第一个1之前的部分,前导0。最后一个1后面的部分,后导0。其它是主体部分。
令1的个数等于cnt,如果cnt不是3的倍数,直接返回{-1,-1}。
令 m = cnt/3。 将1的下标放到indexs中。
判断主体部分是否相等
枚举 i = 0 to m
如果 indexs[i] - indexs[0] 和indexs[i+m] - indexs[m] 和 indexs[i+m2] - indexs[m2]不相等,则返回{-1,-1}。
判断后导0
cnt2 = arr.lenght()- ( indexs.back()+1)
如果 indexs[m] - indexs[m-1] -1 <cnt2 或indexs[2m] - indexs[2m-1] -1 <cnt2 则后导0不足,则返回{-1,-1}。
最终返回值:{indexs[m-1]+m,indexs[2*m]-前导0数量)
代码
核心代码
class Solution {
public:
vector<int> threeEqualParts(vector<int>& arr) {
vector<int> indexs;
for (int i = 0; i < arr.size(); i++) {
if (0 == arr[i]) { continue; }
indexs.emplace_back(i);
}
if (indexs.empty()) { return { 0,(int)arr.size()-1 }; }
if (0 != indexs.size() % 3) { return { -1,-1 }; };
const int m = indexs.size() / 3;
for (int i = 0; i < m; i++) {
const int i1 = indexs[i] - indexs[0];
const int i2 = indexs[i+m] - indexs[m];
const int i3 = indexs[i+2*m] - indexs[2*m];
if ((i1 != i2) || (i2 != i3)) { return { -1,-1 }; }
}
const int i0End = arr.size() - (indexs.back() + 1);
const int iHas1 = indexs[m] - indexs[m - 1]-1;
const int iHas2 = indexs[m * 2] - indexs[m * 2 - 1]-1;
if ((iHas1 < i0End) || (iHas2 < i0End)) { return { -1,-1 }; }
return { indexs[m - 1]+i0End,indexs[m * 2]- (iHas2-i0End) };
}
};
单元测试
template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{
Assert::AreEqual(t1 , t2);
}
template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
Assert::AreEqual(v1.size(), v2.size());
for (int i = 0; i < v1.size(); i++)
{
Assert::AreEqual(v1[i], v2[i]);
}
}
template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
sort(vv1.begin(), vv1.end());
sort(vv2.begin(), vv2.end());
Assert::AreEqual(vv1.size(), vv2.size());
for (int i = 0; i < vv1.size(); i++)
{
AssertEx(vv1[i], vv2[i]);
}
}
namespace UnitTest
{
vector<int> arr;
TEST_CLASS(UnitTest)
{
public:
TEST_METHOD(TestMethod0)
{
arr = { 1, 0, 1, 0, 1 };
auto res = Solution().threeEqualParts(arr);
AssertEx({ 0, 3 }, res);
}
TEST_METHOD(TestMethod1)
{
arr = { 1, 1, 0, 1, 1 };
auto res = Solution().threeEqualParts(arr);
AssertEx({ -1,-1 }, res);
}
TEST_METHOD(TestMethod2)
{
arr = { 1, 1, 0, 0, 1 };
auto res = Solution().threeEqualParts(arr);
AssertEx({ 0,2 }, res);
}
TEST_METHOD(TestMethod3)
{
arr = { 0,0,0,0,0 };
auto res = Solution().threeEqualParts(arr);
AssertEx({ 0,4 }, res);
}
};
}
扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关下载
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
我想对大家说的话 |
---|
《喜缺全书算法册》以原理、正确性证明、总结为主。 |
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。