Task description
A non-empty zero-indexed array A consisting of N integers is given. A peak is an array element which is larger than its neighbors. More precisely, it is an index P such that 0 < P < N − 1, A[P − 1] < A[P] and A[P] > A[P + 1]. For example, the following array A: A[0] = 1 A[1] = 2 A[2] = 3 A[3] = 4 A[4] = 3 A[5] = 4 A[6] = 1 A[7] = 2 A[8] = 3 A[9] = 4 A[10] = 6 A[11] = 2 has exactly three peaks: 3, 5, 10. We want to divide this array into blocks containing the same number of elements. More precisely, we want to choose a number K that will yield the following blocks:
What's more, every block should contain at least one peak. Notice that extreme elements of the blocks (for example A[K − 1] or A[K]) can also be peaks, but only if they have both neighbors (including one in an adjacent blocks). The goal is to find the maximum number of blocks into which the array A can be divided. Array A can be divided into blocks as follows:
However, array A cannot be divided into four blocks, (1, 2, 3), (4, 3, 4), (1, 2, 3) and (4, 6, 2), because the (1, 2, 3) blocks do not contain a peak. Notice in particular that the (4, 3, 4) block contains two peaks: A[3] and A[5]. The maximum number of blocks that array A can be divided into is three. Write a function:
that, given a non-empty zero-indexed array A consisting of N integers, returns the maximum number of blocks into which A can be divided. If A cannot be divided into some number of blocks, the function should return 0. For example, given: A[0] = 1 A[1] = 2 A[2] = 3 A[3] = 4 A[4] = 3 A[5] = 4 A[6] = 1 A[7] = 2 A[8] = 3 A[9] = 4 A[10] = 6 A[11] = 2 the function should return 3, as explained above. Assume that:
Complexity:
Elements of input arrays can be modified. |
1.当maxD大于N/2时,则显然只能分为两部分;
2.当k大于maxD时,k只要能被N整除即是可能解;
3.当k小于等于maxD时,若存在某个分组中无peak,则k不是可能解;
代码:
// you can use includes, for example:
#include
// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;
int solution(vector
&A) {
// write your code in C++11
int maxD = 0;//相邻peak间的最大距离
int N = A.size();
vector
peakSum(N+1,0);//存储第i个元素(不含)之前的peak数量
int lastpeak = -1;//考虑第一个peak到数组最前端的距离
for(int i=1;i
A[i-1]&&A[i]>A[i+1])
{
peakSum[i+1] = peakSum[i] + 1;
maxD = max(maxD,i - lastpeak);
lastpeak = i;
}
else
{
peakSum[i+1] = peakSum[i];
}
}
peakSum[N]=peakSum[N-1];
if(peakSum[N]==0)//若第N个元素之前无peak,则返回0
return 0;
maxD = max(maxD,N - lastpeak);//考虑最后一个peak到尾部的距离
if(maxD > N/2)//若相邻两peak间最大距离超过N/2,则必然只能分为两部分
return 1;
for(int k = maxD/2;k<=maxD;++k)
{
if(N%k==0)
{
bool isvalid = true;
int c = N/k;
for(int i=1;i<=c;++i)
{
if(peakSum[i*k]==peakSum[(i-1)*k])//若数组拆分后第i部分之前和第i-1部分之前peak数一样
//则第i部分无peak,方案不合理
isvalid = false;
}
if(isvalid)
return c;
}
}
for(int k = maxD+1;;k++)//若每部分的长度k大于maxD+1,则只要k能被N整除,这种划分就是合理的
{
if(N%k==0) return N/k;
}
}