从leetcode(hard)135说开去

原题链接:https://leetcode.com/problems/candy/?tab=Description
135. Candy
There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?

题目大意是:一群小孩战成一列,每个人都有一个评分值,每个小孩至少得到1颗糖,分值比它旁边的人高的小孩得到的糖比旁边的人多,问:至少要给出多少糖?

这题需要注意的一个坑是:如果相邻的两个人分值是相同的,那么他们手里的糖不一定要相等,比如:如果分值的序列是这样的2 2 1,分配的糖果是1 2 1,而不是2 2 1.

我的思维是:先找出分值最少的小孩,给他一颗糖,然后左右分治,分别找出左右分值最少的小孩,如果找到的这个小孩的左右没有任何一个拿过糖,那么就给这个小孩一颗糖,否则,依据左右已经得到糖的孩子手里的糖的数量以及分值,决定这个孩子得到多少糖。
代码如下:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

class Solution {
public:
    int* divide;
    int* formal;
    int full_num;
    int find_min(int *start, int num)
    {
        if (num <= 0) return -1;
        int a = *start;
        int id = 0;
        for (int i = 1; i < num; ++i)
        {
            if (a>*(start + i)) a = *(start + i), id = i;
        }
        return id;
    }
    void fenzhi(int *formal,int start, int num)
    {
        if (num <= 0) return;
        int index = find_min(formal + start, num) + start;
        if (index + 1 >= full_num)
        {
            if (*(divide + index - 1) == 0) *(divide + index) = 1;
            else if (*(formal + index - 1) == *(formal + index)) *(divide + index) = 1;
            else *(divide + index) = *(divide + index - 1) + 1;
        }
        else if (index - 1 < 0)
        {
            if (*(divide + index + 1) == 0) *(divide + index) = 1;
            else if (*(formal + index + 1) == *(formal + index)) *(divide + index) = 1;
            else *(divide + index) = *(divide + index + 1) + 1;
        }
        else if (*(divide + index + 1) == 0)
        {
            if (*(divide + index - 1) == 0) *(divide + index) = 1;
            else if (*(formal + index - 1) == *(formal + index)) *(divide + index) = 1;
            else *(divide + index) = *(divide + index - 1) + 1;
        }
        else if (*(divide + index - 1) == 0)
        {
            if (*(divide + index + 1) == 0) *(divide + index) = 1;
            else if (*(formal + index + 1) == *(formal + index)) *(divide + index) = 1;
            else *(divide + index) = *(divide + index + 1) + 1;
        }
        else
        {
            if (*(formal + index + 1) == *(formal + index))
            {
                *(divide + index) = 1;
                if (*(formal + index - 1) < *(formal + index) && *(divide + index - 1) >= *(divide + index)) *(divide + index) = *(divide + index - 1) + 1;
            }
            else if (*(formal + index - 1) == *(formal + index))
            {
                *(divide + index) = 1;
                if (*(formal + index + 1) < *(formal + index) && *(divide + index + 1) >= *(divide + index)) *(divide + index) = *(divide + index + 1) + 1;
            }
            else if (*(divide + index + 1) > *(divide + index - 1)) *(divide + index) = *(divide + index + 1) + 1;
                else *(divide + index) = *(divide + index - 1) + 1;
        }
        fenzhi(formal, start, index - start);
        fenzhi(formal, index + 1, num - index + start - 1);
    }


    int candy(vector<int>& ratings) 
    {
        full_num = ratings.size();
        divide = new int[full_num];
        formal = new int[full_num];
        for (int i = 0; i < full_num; ++i) *(divide + i) = 0;
        for (int i = 0; i < full_num; ++i) *(formal + i) = ratings[i];
        if (full_num == 1) return 1;
        fenzhi(formal, 0, full_num);
        int sum = 0;
        for (int i = 0; i < full_num; ++i)
        {
            sum += *(divide + i);
        }
        delete [] formal;
        delete [] divide;
        return sum;
    }
};

int main()
{
    vector<int> ratings = { 1,3,4,3,2,1 };
    Solution a;
    int outx = a.candy(ratings);
    cout << outx;
    getchar(); getchar();
    return 0;

}

代码很长,时间成本很高,虽然可以通过leetcode的评测,但是这显然不是可以接受的方法,下面对评论区大神的代码做一些分析。

对于种左右比较的题目,分别对每个数的要求可以归纳为:
1. 如果当前孩子的分值比左边孩子高,他的糖果要比左边孩子多
2. 如果当前孩子的分值比右边孩子高,他的糖果要比右边孩子多

我的思维定式是,一个一个孩子去讨论,比如说我的思维定式就是从小到大往里填数据,但是更好的思维方式是:将上面的情况1作为一个大类讨论,情况2作为另一个情况讨论
具体而言,先从左到右遍历一遍,确保当前孩子的分值比左边孩子高,他的糖果要比左边孩子多,再从右到左遍历一遍,确保当前孩子的分值比右边孩子高,他的糖果要比右边孩子多。

代码如下:

  int candy(vector<int> &ratings)
 {
     int size=ratings.size();
     if(size<=1)
         return size;
     vector<int> num(size,1);
     for (int i = 1; i < size; i++)
     {
         if(ratings[i]>ratings[i-1])
             num[i]=num[i-1]+1;
     }
     for (int i= size-1; i>0 ; i--)
     {
         if(ratings[i-1]>ratings[i])
             num[i-1]=max(num[i]+1,num[i-1]);
     }
     int result=0;
     for (int i = 0; i < size; i++)
     {
         result+=num[i];
        // cout<<num[i]<<" ";
     }
     return result;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值