leetcode candy分糖果问题 两次遍历和一次遍历

21 篇文章 0 订阅

here 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. 数组rating :2,4,3,2
  2. 分糖果:1,3,2,1

    两次遍历:
    先从头开始,后面大的比前面多一个

public int candy(int[] ratings) {  
        int size = ratings.length;  
        if (size == 0) return -1;  
        if (size == 1) return 1;  

        int[] cans = new int[size];  
        cans[0] = 1;  
        //正向扫描一遍,如果右边的rating比左边高,那么右边的糖果数就比左边多一个,否则只给一个糖果  
        for (int i = 1; i < size; i++) {  
            if (ratings[i] > ratings[i - 1]) cans[i] = cans[i - 1] + 1;  
            else cans[i] = 1;  
        }  
        //反向扫描一遍,如果左边的rating比右边高,并且左边的糖果数比右边少,那么左边的糖果数应比右边多一  
        for (int i = size - 2; i >= 0; i--) {  
            if (ratings[i] > ratings[i + 1] && cans[i] <= cans[i + 1]) {  
                cans[i] = cans[i + 1] + 1;  
            }  
        }  

        int ret = 0;  //实际上这里可以把ret在上面一个循环中加,减少一次循环,不过本文主要是来实现一次循环,这个简单,大家都会
        for (int i = 0; i < size; i++) {  
            ret += cans[i];  
        }  

        return ret;  
    }  

一次遍历:利用等差数列

 public int candy(int[] ratings) {
        if (ratings == null || ratings.length == 0) return 0;
        int total = 1, prev = 1, countDown = 0;
        for (int i = 1; i < ratings.length; i++) 
        {
            if (ratings[i] >= ratings[i-1])
             {
                if (countDown > 0) 
                {
                    total += countDown*(countDown+1)/2; // 1+2+3+4=(1+4)*4/2 
                    if (countDown >= prev) total += countDown - prev + 1;//如果,连续的等级下降的孩子个数,大于这个下降孩子序列之前的那个孩子的分的糖果数,需要对那个孩子,再加糖果
                    countDown = 0;
                    prev = 1;
                }
                prev = ratings[i] == ratings[i-1] ? 1 : prev+1;//比较当前i位置处值和前面的i-1处,是否相等,不等,则需要比i-1处多一个糖果
                total += prev;
            } 
            else countDown++;
        }
        if (countDown > 0) { // if we were descending at the end
            total += countDown*(countDown+1)/2;
            if (countDown >= prev) total += countDown - prev + 1;
        }
        return total;
    }

prev表示的是孩子分的糖果,不断更行。countDown表示的是右边孩子的等级比左边低的孩子个数。
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值