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;
}
     
原文地址:https://www.cnblogs.com/codingmylife/p/2632279.html