Candy 根据排名分糖果 @LeetCode

一些例子:

1 2 3 3 3 =》 8 因为candy数可以是

1 2 3 1 1

1 2 3 2 3 =》9 因为candy数可以是

1 2 3 1 2


思路:

1

  • d[i] 是给第i个小孩最少几块糖
    • rank[i] > rank[i - 1],必须比前一个多给一块,d[i] = d[i - 1] + 1
    • rank[i] == rank[i - 1],两个排名一样,第二个就给一块就行了, d[i] = 1
    • rank[i] < rank[i - 1],比上一个排名低,应该少给一块,但是若上一个已经只给一块了,就得往前推一个一个多给。推到什么时候为止呢?若排名比下一个高,糖还一样多,就得再给;直到这个关系打破(排名一样或比下一个还低,或是糖已经满足关系)就不用再往前推了。
http://leetcodenotes.wordpress.com/2013/10/08/leetcode-candy-%E7%BB%99%E5%B0%8F%E5%AD%A9%E5%AD%90%E5%88%86%E7%B3%96/comment-page-1/#comment-123

或者

  • use store[] to store the kid's candy result
  • give first kid[0] candy
  • start loop : from index 1 to n
    • if the ratings[i] > ratings[i - 1], ascending order, just store[i] = store[i-1] + 1
    • if ==, we can make it down to 1 (according to the condition)
    • if the ratings[i] < ratings[i - 1], descending order, store[i] = 1;
      • at the same time. we have to check if the store[i] == store[i-1] while ratings[i-1] is higher
      • if so, make this previous store++
      • continue, check previous one, until find previous ratings is not high or previous store is not equal to the later one
  • time (n^2) worst time is {6,5,4,3,2,1}
  • space (n)
http://vialgorithms.blogspot.com/2013/10/candy.html


2 从左向右扫,再从右向左扫,这样就能满足题目的条件。在第二次扫描时顺便记录总共需要的candy数

http://joycelearning.blogspot.com/2013/10/leetcode-candy.html

http://blog.csdn.net/violet_program/article/details/12233949


package Level5;

/**
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?

 */
public class S145 {

	public static void main(String[] args) {
		int[] ratings = {5,3,1};
		System.out.println(candy(ratings));
	}
	
	// O(n)
	public static int candy(int[] ratings) {
		int len = ratings.length;
		if(len == 0){
			return 0;
		}
		int min = len;
		int[] candies = new int[len];
		
		int cur = 0;
		// 从第2个孩子扫描到结尾,比较每个孩子和他的左邻居
		for(int i=1; i<len; i++){
			if(ratings[i] > ratings[i-1]){
				cur++;
			}else{
				cur = 0;
			}
			candies[i] = cur;
		}
		
		cur = 0;
		// 从倒数第二个孩子扫描到第一个孩子,比较每个孩子和他的右邻居
		for(int i=len-2; i>=0; i--){
			if(ratings[i] > ratings[i+1]){
				cur++;
			}else{
				cur = 0;
			}
			candies[i] = Math.max(candies[i], cur);
			min += candies[i];
		}
		
		// 别忘了加上最后一个孩子的candy数
		min += candies[len-1];
		return min;
	}
	
	
	// O(n2) TLE
	public static int candy2(int[] ratings) {
        if(ratings.length == 0){
        	return 0;
        }
        
        int[] candies = new int[ratings.length];
        candies[0] = 1;
        for(int i=1; i<candies.length; i++){
        	if(ratings[i] > ratings[i-1]){
        		candies[i] = candies[i-1]+1;
        	}else if(ratings[i] == ratings[i-1]){
        		candies[i] = 1;
        	}else{
        		candies[i] = 1;
        		if(candies[i-1] == 1){
        			int j = i;
        			while(j > 0 && ratings[j-1]>ratings[j]){
        				candies[j-1]++;
        				j--;
        			}
        		}
        	}
        }
        
        int count = 0;
        for(int val : candies){
        	count += val;
        }
        return count;
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值