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?

Solution:

最开始想到的是 从左往右循环,如果遇到 左边小于右边的, 右边的+1。 遇到左边大于右边的, 回退,直到右边大于左边,给每一个元素+1, 这样时间复杂度是O(n^2)。 得降:

接着就想到用stack,循环从左边开始,如果发现左边比右边大 则入stack,直到左边比右边小 ,然后出stack,给每个出stack的数加上其在stack里面的位置,即深度。

如果当前点比它前面的点大呢? candy[i] = candy[i - 1] + 1; 否则, candy[i] = 1;

这里新建了一个数组,rating, 它扩展了原数组,末尾加了一个-1, 用于对最后一个元素进行判断。

对于栈底元素,即临界元素,其值应该等于左边得到的值 和通过栈的到的值中间最大的那一个。

还要在循环外, 对stack进行一次操作。

对最后一个点 还得讨论,

1)如果最后一个点 比 前一个小 则不变
2)比前一个大 则为D(n -1) + 1
 
464 ms过大测试~~时间复杂度 O(n)。
 1 public class Solution {

 2     public int candy(int[] ratings) {

 3         // Note: The Solution object is instantiated only once and is reused by each test case.

 4         int l = ratings.length;

 5         int[] rating = new int[l + 1];

 6         for(int i = 0; i < l; i ++){

 7             rating[i] = ratings[i];

 8         }

 9         rating[l] = -1;

10         int sum = 0;

11         int d = 0;

12         int[] candy = new int[l];

13         Stack<Integer> st = new Stack<Integer>();

14         for(int i = 0; i < l; i ++){

15             if(i > 0 && rating[i] > rating[i - 1]){

16                 candy[i] = candy[i - 1] + 1;

17             }else{

18                 candy[i] = 1;

19             }

20             if(rating[i] > rating[i+1]){

21                 st.push(i);

22             }else{

23                 d = st.size();

24                 if(d > 0){

25                     for(int ii = 0; ii < d - 1; ii ++){

26                         int cur = st.pop();

27                         candy[cur] += ii+1;

28                     }

29                     int cur = st.pop();

30                     candy[cur] = ((d + 1) > candy[cur] ? (d + 1) : candy[cur]);// d+1 原因: 最小的那个元素没有入栈,栈的深度少了1.

31                 }

32             }

33             

34         }

35         d = st.size();

36         for(int ii = 0; ii < d - 1; ii ++){

37             int cur = st.pop();

38             candy[cur] += ii;

39         }

40         int cur = st.pop();

41         candy[cur] = (d > candy[cur] ? d : candy[cur]);

42         for(int i = 0; i < candy.length; i ++){

43             sum += candy[i];

44         }

45         return sum;

46     }

47 }

 其实,这一题可以想象成一个波, 它有上升和下降。 第一遍,考虑上升的所以情况; 第二遍,考虑下降的所以情况。 然后对于波峰,用两边的max 值当成它的值即可。

这样 思路变得更加清晰。 

 1 public class Solution {

 2     public int candy(int[] ratings) {

 3         // Note: The Solution object is instantiated only once and is reused

 4 //by each test case.

 5         int rLen = ratings.length;

 6         if (rLen == 0) return 0;

 7         int min = rLen; int give = 0;

 8         int[] gives = new int[rLen];

 9         for (int i = 1; i < rLen; i++) {

10             if (ratings[i] > ratings[i - 1]) give++;

11             else give = 0;

12             gives[i] = give;

13         }

14         give = 0;

15         for (int i = rLen - 2; i >= 0; i--) {

16             if (ratings[i] > ratings[i + 1]) give++;

17             else give = 0;

18             min += Math.max(give, gives[i]);

19         }

20         min += gives[rLen - 1];

21         return min;

22     }

23 }

 find out all local min rating, 
for each local min rating, start with 1 candy, and expand on both directions
until hit by local max.
return total candies.

O(n)

 

第二遍: 波的方法, 左边走一次右边走一次。

 1 public class Solution {

 2     public int candy(int[] ratings) {

 3         // Note: The Solution object is instantiated only once and is reused by each test case.

 4         if(ratings == null || ratings.length == 0) return 0;

 5         int len = ratings.length;

 6         int[] candy = new int[len];

 7         int sum = 0;

 8         for(int i = 0; i < len; i ++)

 9             candy[i] = 1;

10         for(int i = 1; i < len; i ++){

11             if(ratings[i - 1] < ratings[i]) candy[i] = candy[i - 1] + 1;

12         }

13         for(int i = len - 1; i > 0; i --){

14             if(ratings[i] < ratings[i - 1]) candy[i - 1] = Math.max(candy[i - 1], candy[i] + 1);

15         }

16         for(int i = 0; i < len; i ++)

17             sum += candy[i];

18         return sum;

19     }

20 }

 

你可能感兴趣的:(ca)