LeetCode:Candy

题目地址:here

题目大意:几个小孩站一排,每个小孩有个等级值,现在给小孩发糖,发的时候要遵守2个规则:(1)每个小孩至少一颗糖(2)两个相邻的小孩中,等级大的小孩一定比等级小的小孩糖多,求发糖的数目的最小值。

本文提供两个算法,第一个是我自己做题时用的,第二个是网上看题解时看到的

算法1:该算法采用分治发,把小孩平均分左右两拨,求得两拨小孩的最小值分配方案后,还得看分界线出是否满足规则。我们用L[end]表示左边一拨小孩的右边界,R[start]表示右边一拨小孩的左边界,处理分界线出的情况分以下两种:

(1)如果L[end]等级比R[start]高,但是糖数少或相等,那么就从左边一拨小孩的右边界依次调整糖数以满足规则;

(2)如果L[end]等级比R[start]低,但是糖数多或相等,那么就从右边一拨小孩的左边界依次调整糖数以满足规则;

该算法时间复杂度为O(N*lgN)

算法1代码如下:

 1 class Solution {
 2 public:
 3     int candy(vector<int> &ratings)
 4     {
 5         // Note: The Solution object is instantiated only once and is reused by each test case.
 6         int *candyNum = new int[ratings.size()];//每个小孩的糖数目
 7         memset(candyNum,0,sizeof(int)*ratings.size());
 8         int result = candyRecursive(ratings, 0, ratings.size()-1, candyNum);
 9         delete []candyNum;
10         return result;
11     }
12 
13     int candyRecursive(vector<int> &ratings, int startloc, int endloc,
14                      int candyNum[])
15     {
16         if(startloc == endloc)
17         {
18             candyNum[startloc] = 1;
19             return 1;
20         }
21         int middle = (startloc + endloc)/2;
22         int rightCandy = candyRecursive(ratings, middle+1, endloc, candyNum);
23         int leftCandy = candyRecursive(ratings, startloc, middle, candyNum);
24         if(ratings[middle+1] > ratings[middle])
25         {
26             int tmp = candyNum[middle+1] - candyNum[middle];
27             if(tmp <= 0)
28             {
29                 tmp *= -1;
30                 candyNum[middle+1] += (tmp+1);
31                 rightCandy += (tmp+1);
32                 for(int i = middle+2; i <= endloc; i++)
33                 {
34                     if(ratings[i] > ratings[i-1] && candyNum[i] <= candyNum[i-1])
35                     {
36                         int foo = candyNum[i-1] - candyNum[i] + 1;
37                         candyNum[i] += foo;
38                         rightCandy += foo;
39                     }
40                     else break;
41                 }
42             }
43         }
44         else if(ratings[middle+1] < ratings[middle])
45         {
46             int tmp = candyNum[middle+1] - candyNum[middle];
47             if(tmp >= 0)
48             {
49                 candyNum[middle] += (tmp+1);
50                 leftCandy += (tmp+1);
51                 for(int i = middle-1; i >= startloc; i--)
52                 {
53                     if(ratings[i] > ratings[i+1] && candyNum[i] <= candyNum[i+1])
54                     {
55                         int foo = (candyNum[i+1] - candyNum[i] + 1);
56                         candyNum[i] += foo;
57                         leftCandy += foo;
58                     }
59                     else break;
60                 }
61             }
62         }
63         return leftCandy + rightCandy;
64     }
65 };

算法2:初始化所有小孩糖数目为1,从前往后扫描,如果第i个小孩等级比第i-1个高,那么i的糖数目等于i-1的糖数目+1;从后往前扫描,如果第i个的小孩的等级比i+1个小孩高,但是糖的数目却小或者相等,那么i的糖数目等于i+1的糖数目+1。

该算法时间复杂度为O(N)

算法2代码如下:

 1 class Solution {
 2 public:
 3     int candy(vector<int> &ratings)
 4     {
 5         // Note: The Solution object is instantiated only once and is reused by each test case.
 6         int *candyNum = new int[ratings.size()];//每个小孩的糖数目
 7         for(int i = 0; i < ratings.size(); i++)
 8             candyNum[i] = 1;
 9         for(int i = 1; i < ratings.size(); i++)
10             if(ratings[i] > ratings[i-1])
11                 candyNum[i] = candyNum[i-1] + 1;
12         for(int i = ratings.size()-2; i>=0; i--)
13             if(ratings[i] > ratings[i+1] && candyNum[i] <= candyNum[i+1])
14                 candyNum[i] = candyNum[i+1] + 1;
15         int result = 0;
16         for(int i = 0; i < ratings.size(); i++)
17             result += candyNum[i];
18         delete []candyNum;
19         return result;
20     }
21 };

 【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3389479.html

原文地址:https://www.cnblogs.com/TenosDoIt/p/3389479.html