Interview Street Challenges - Candies
链接:https://www.interviewstreet.com/challenges/dashboard/#problem/4fe12e4cbb829
分析:可以把rating看成一个有升有降的数组,然后数组中存在三种区域(连续升、连续降、水平),区域的最小长度为1。举个例子,rating[] = [1, 2, 3, 3, 4, 2],则direction[] = [↑, ↑, 〓, ↑, ↓]。对于每个连续区间,都从1开始计数(连续升的,从1开始递增;连续降的看成从右向左的连续升,相等的始终为1),并且记录左右边界值。以前面例子,可以分成[1, 2, 3] {left = 1, right = 3}、[1, 1] {left = 1, right = 1}、[1, 2] {left = 1, right = 2}、[2, 1] {left = 2, right = 1}这几个区间。
现在如何利用区间数据来计算Candies呢?
section | 1 | 2 | 3 | 1 | 2 | |
section | 1 | 1 | 2 | 1 | ||
rating | 1 | 2 | 3 | 3 | 4 | 2 |
这样看来,只需在区间交错位置取最大值即可,其它直接累加区间值,最终结果就是Candies数。此例中Candies = 1 + 2 + 3 (max(3, 1)) + 1 (max(1, 1)) + 2 (max(2, 2)) + 1 = 1 + 2 + 3 + 1 + 2 + 1 = 10。
代码(AC):
#include <cstdio>
#include <memory.h>
using namespace std;
int max(int a, int b)
{
return a > b ? a : b;
}
// Calculate the section candies without boundary value,
// the boundary value will be set to left and right.
int continual_section_candies(int *rating, int begin, int end, int *left, int *right)
{
int sum = 0;
if (rating[begin] < rating[end])
{
*left = 1;
*right = end - begin + 1;
sum += (*left + *right) * (*right) / 2;
sum -= *left;
sum -= *right;
}
else if (rating[begin] > rating[end])
{
*right = 1;
*left = end - begin + 1;
sum += (*left + *right) * (*left) / 2;
sum -= *left;
sum -= *right;
}
else
{
sum += (end - begin - 1);
*left = 1;
*right = 1;
}
return sum;
}
int get_direction(int left, int right)
{
if (left < right)
return 1;
if (left > right)
return -1;
return 0;
}
int main(int argc, char **argv)
{
int rating[100005];
int n = 0;
// Get n.
scanf("%d", &n);
// Handle special case.
if (n <= 0)
{
printf("0");
return 0;
}
else if (n == 1)
{
printf("1");
return 0;
}
// Init and read rating.
memset(rating, 0, sizeof(rating));
for (int i = 0; i < n; ++i)
{
scanf("%d", rating + i);
}
// Add a special value in rating end to
// make sure the rating end will be detected as a section end.
rating[n] = rating[n - 1] == rating[n - 2] ?
rating[n - 1] + 1 : rating[n - 2];
// Update n.
++n;
int candies = 0;
int last_inflection_pos = 0;
int last_inflection_value = 0;
for (int i = 1; i < n - 1; ++i)
{
const int left_direction = get_direction(rating[i - 1], rating[i]);
const int right_direction = get_direction(rating[i], rating[i + 1]);
if (left_direction != right_direction)
{
int left, right;
candies += continual_section_candies(rating, last_inflection_pos, i, &left, &right);
candies += max(left, last_inflection_value);
last_inflection_pos = i;
last_inflection_value = right;
}
}
candies += last_inflection_value;
printf("%d", candies);
return 0;
}