题目来源:https://leetcode.com/contest/weekly-contest-107/problems/three-equal-parts/
问题描述
927. Three Equal Parts
Given an array A
of 0
s and 1
s, divide the array into 3 non-empty parts such that all of these parts represent the same binary value.
If it is possible, return any [i, j]
with i+1 < j
, such that:
A[0], A[1], ..., A[i]
is the first part;A[i+1], A[i+2], ..., A[j-1]
is the second part, andA[j], A[j+1], ..., A[A.length - 1]
is the third part.- All three parts have equal binary value.
If it is not possible, return [-1, -1]
.
Note that the entire part is used when considering what binary value it represents. For example, [1,1,0]
represents 6
in decimal, not 3
. Also, leading zeros are allowed, so [0,1,1]
and [1,1]
represent the same value.
Example 1:
Input: [1,0,1,0,1]
Output: [0,3]
Example 2:
Input: [1,1,0,1,1]
Output: [-1,-1]
Note:
3 <= A.length <= 30000
A[i] == 0
orA[i] == 1
------------------------------------------------------------
题意
给定一个0和1组成的int数组,问能否把这个数组分成三个部分,使得每个部分组成的二进制整数数值相等(忽略先导零)
------------------------------------------------------------
思路
一开始以为是个三分搜索题,想了半天没有想出来压缩搜索区间的条件,后来发现其实是个模拟题。J
注意到“每个部分组成的二进制整数数值相等”有两个必要不充分条件:
(1)每个部分含有1的个数相等
(2)每个部分末尾0的个数相等
抓住这两个条件,很容易判断出那些不可行的case,并且唯一确定那些可能可行的case中的分割点。再根据求出的分割点分别计算三个部分对应的二进制整数值,就可以最终判断是否可行。
O(n)算法。
------------------------------------------------------------
代码
class Solution {
public:
int cal_bin(vector<int>& A, int beg, int end)
{
int i, j = 1, ret = 0;
for (i=end-1; i>=beg; i--)
{
ret += A[i]*j;
j <<= 1;
}
return ret;
}
vector<int> threeEqualParts(vector<int>& A) {
int i, len = A.size(), cnt1 = 0, cnt = 0, m1 = -1, m2 = -1, tail0 = 0, lv, mv, rv;
vector<int> ans;
for (i=0; i<len; i++)
{
cnt1 += A[i]; // cnt1: # of '1's in vector A
}
if (cnt1 == 0)
{
ans.push_back(0);
ans.push_back(2);
return ans;
}
else if (cnt % 3 != 0)
{
ans.push_back(-1);
ans.push_back(-1);
return ans;
}
else
{
cnt = 0;
tail0 = 0; // tail0: # of '0's behind last '1', also # of '0's at the end of third binary number
for (i=0; i<len; i++)
{
cnt += A[i];
if (m1 == -1 && cnt == cnt1/3)
{
m1 = i; // possible end of second binary number
}
else if (m2 == -1 && cnt == cnt1*2/3)
{
m2 = i; // possible end of third binary number
}
else if (cnt == cnt1 && A[i] == 0)
{
tail0++;
}
}
for (i=m1+1; i <= m1 + tail0; i++)
{
if (A[i] == 1) // not enough '0's at the end of first binary number
{
ans.push_back(-1);
ans.push_back(-1);
return ans;
}
}
for (i=m2+1; i<=m2+tail0; i++)
{
if (A[i] == 1) // not enough '0's at the end of second binary number
{
ans.push_back(-1);
ans.push_back(-1);
return ans;
}
}
m1 += tail0;
m2 += tail0;
lv = cal_bin(A, 0, m1+1);
mv = cal_bin(A, m1+1, m2+1);
rv = cal_bin(A, m2+1, len);
if (lv == mv && mv == rv)
{
ans.push_back(m1);
ans.push_back(m2+1);
}
else
{
ans.push_back(-1);
ans.push_back(-1);
}
return ans;
}
}
};