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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM