135. Candy

一、题目

  1、审题

  

  2、分析

    每个小孩对应一个等级,每个小孩至少分一颗糖,紧挨着的等级高的小孩要比紧挨着的等级低的小孩的糖果多,求至少要分几颗糖果。

 

二、解答

  1、思路: 

    方法一、

      考虑到每个小孩的分到的糖果数受左右两边的小孩等级的影响。故:

      ①、找出所有小孩中等级最低的小孩1,分一棵糖,且他左边若有小孩2且等级高于小孩1,则赋小孩2糖果为 小孩1糖果 + 1,最终小孩2 分的糖果要大于等于此数。

        同理,小孩1 右边的同伴小孩3 若等级大于小孩1,也先分配 (小孩1)+1,小孩3最终分配的糖果要大于次数。

      ②、将小孩1左边的所有小孩按照 ① 继续递归,将小孩1右边的小孩按照①递归。

      ③、最终将所有小孩分配的糖果相加即可。

public int candy(int[] ratings) {
        
        int len = ratings.length;
        int[] cost = new int[len];
        
        candyHelper(ratings, cost, 0, len - 1);
        
        int result = 0;
        for (int i = 0; i < len; i++) 
            result += cost[i];
        return result;
    }
    
    private void candyHelper(int[] ratings, int[] cost, int start, int end) {
        
        if(start > end)
            return;
        
        int minIndex = start; // rating 最小的下标
        for (int j = start + 1; j <= end; j++) {
            if(ratings[minIndex] > ratings[j])
                minIndex = j;
        }
        
        cost[minIndex] = Math.max(cost[minIndex], 1);
        
        
        if(minIndex -1 >= start && ratings[minIndex - 1] != ratings[minIndex])  // 与左边不相等
                cost[minIndex - 1] = Math.max(cost[minIndex - 1], cost[minIndex] + 1);
        
        if(minIndex + 1 <= end && ratings[minIndex + 1] != ratings[minIndex]) // 与右边不相等
            cost[minIndex + 1] = Math.max(cost[minIndex + 1], cost[minIndex] + 1);
        
        
        candyHelper(ratings, cost, start, minIndex - 1);
        candyHelper(ratings, cost, minIndex + 1, end);
    }

 

   方法二、

    ①、新建一个 cost 数组,初值均为 1;

    ②、从前向后遍历 ratings ,若后一个元素的 rating 大于前一个,则 后一个元素的 cost 为 前一个的 cost 值 + 1

    ③、从后向前遍历 ratings,若前一个元素的 rating 大于后一个,则前一个元素的 cost 为 当前 cost 与 后一个cost值 + 1 的两者最大值。

    public int candy2(int[] ratings) {
        
        int len = ratings.length;
        if(len < 2)
            return len;
        int[] cost = new int[len];
        Arrays.fill(cost, 1);
        
        // Scan from left to right, to make sure right higher rated child gets 1 more candy than left lower rated child
        for (int i = 1; i < len; i++) {
            if(ratings[i] > ratings[i - 1])
                cost[i] = cost[i - 1] + 1;
        }
        // Scan from right to left, to make sure left higher rated child gets 1 more candy than right lower rated child
        for (int i = len - 1; i > 0; i--) {
            if(ratings[i - 1] > ratings[i])
                cost[i - 1] = Math.max(cost[i - 1], cost[i] + 1);
        }
        
        int result = 0;
        for (int i = 0; i < len; i++) 
            result += cost[i];
        return result;
    }

 

posted @ 2018-10-10 11:47  skillking2  阅读(177)  评论(0编辑  收藏  举报