Candy(LeetCode)

来源:互联网 发布:淘宝评价语搞笑 编辑:程序博客网 时间:2024/06/03 22:57

题目:

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?

题目分析:题目假设,有N个小孩子站成一条线。每个小孩子都有个分数rating。现在,你要给每个小孩子发糖。每个小孩子至少得分到一颗糖。对于两个相邻的小孩子,得分高的孩子必须得到糖的数目要比的得分低得孩子的糖要多。注意!当两个相邻的小孩子,得分一样时,其中一个小孩子可以比另一个孩子得到的糖要多。问你最少得发多少颗糖?


思路:

  1. 题目规定,每个孩子必须有一个糖,所以先给每个孩子都发一颗糖。
  2. 解题的大致思路是:
    • 得分最少的孩子A肯定只有一颗糖,是不会改变的。
    • 查看他附近的两个(或者一个,或者零个)孩子,如果得分比A高,但现在有的糖也只有一个。让这个A邻近的孩子的糖数,变为在A的基础上加1,变为2.
    • 然后去寻找得分第二少的孩子B。。。。得分第i少的孩子I。。。
    • 对于得分第i少的孩子I,同样查看I的近邻,如果近邻得分比I高,但是糖数没有多过I。让这个近邻的糖数变为在I的基础上加一个。
    • 如此循环,直到得分最高的孩子近邻的糖数被确定(其实,得分次高的孩子被处理过之后,整个糖数就确定了)
  3. 现在的问题是,每次都从剩下的孩子中找到分数最少的。花费的总时间应该是O(n^2)。之前用递归写过这样的算法,LeetCode上提示TimeLimitedExceed错误。
  4. 解决方法是,对孩子的ratings备份,然后进行排序,同时记录下他们的下标index的变化之后的位置
    • 例如,假设ratingsBackup=[5,2,4], index=[0,1,2];排完序之后,ratingsBackup=[2,4,5],index=[1,2,0]
    • 这样,我们从变化之后的index中直到,下标为1的孩子最低,即ratings[1]最小,其次ratings[2],最后ratings[0]
    • 有了index,我们就可以按照孩子的得分从小到大,遍历每一个孩子,然后用2中的方法解决问题
  5. 排序算法的使用
    • 为了减少复杂度,所以先对ratings备份进行了排序。所以排序算法必须得小于O(n^2),否则没有意义了。。。
    • 这里我选择了归并排序(merge sort),归并排序的算法在wiki上可以找到,这里不赘述
    • 值得注意的是,在排序的同时,要记得同时记录孩子们下标的改变(代码中的index)
    • 代码中的mergeSortFindIndex方法就是完成这个任务的。
    • 而merge方法又是被mergeSortFindIndex方法调用,用来完成归并算法中的归并操作的



注意点:

  • 在归并操作(merge方法)中,当对两个有序数组A和B进行归并时(A和B分别为ratings数组中的一段),需要临时存放在一个长度为A.length+B.length的数组C中。
  • 而每次进行归并操作,都新建一个数组C非常耗时。可以在开头声明一个static数组ratingsTemp,大小等同于rantings.length。
  • 在归并A和B时,只需要取A和B在ratingsTemp中对应的部分来用就行了。
  • 这样就避免了,多次创建数组
  • 同样适用于归并操作中的index



代码:

public class Solution {    static int[] ratingsTemp;    static int[] indexTemp;    public int candy(int[] ratings) {        int[] index = new int[ratings.length];        int[] ratingsBackup = new int[ratings.length];        int[] result = new int[ratings.length];        ratingsTemp = new int[ratings.length];        indexTemp = new int[ratings.length];        for (int i = 0; i < ratings.length; i++){            index[i] = i;            ratingsBackup[i] = ratings[i];            result[i] = 1;        }        mergeSortFindIndex(ratingsBackup,index,0,ratings.length-1);                for (int i = 0; i < index.length; i++){            int t = index[i];            if (t > 0){                if(ratings[t-1] > ratings [t] && result[t-1] <= result[t]){                    result[t-1] = result[t] +1;                }            }            if (t < index.length-1){                if (ratings[t+1] > ratings[t] && result[t+1] <= result[t]){                    result[t+1] = result[t] + 1;                }            }        }                int sum = 0;        for (int i = 0; i < result.length; i++){            sum += result[i];        }        return sum;    }        private static void mergeSortFindIndex(int[] ratings, int[] index, int begin, int end){        if (end - begin < 1){            return;        }         mergeSortFindIndex(ratings, index, begin, (begin+end)/2);        mergeSortFindIndex(ratings, index, (begin+end)/2+1, end);        merge(ratings, index, begin, (begin+end)/2, (begin+end)/2+1, end);    }        private static void merge(int[] ratings, int[] index, int begin1, int end1, int begin2, int end2){        int i = begin1;        int i1 = begin1;        int i2 = begin2;        while (i1 <= end1 && i2 <= end2){            if (ratings[i1] <= ratings[i2]){                ratingsTemp[i] = ratings[i1];                indexTemp[i] = index[i1];                i1++;                i++;            }else {                ratingsTemp[i] = ratings[i2];                indexTemp[i] = index[i2];                i2++;                i++;            }        }        if (i1 <= end1){            while (i1 <= end1){                ratingsTemp[i] = ratings[i1];                indexTemp[i] = index[i1];                i1++;                i++;            }        }else{            while (i2 <= end2){                ratingsTemp[i] = ratings[i2];                indexTemp[i] = index[i2];                i2++;                i++;            }        }        for (i = begin1; i <= end2; i++){            ratings[i] = ratingsTemp[i];            index[i] = indexTemp[i];        }    }}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 被自家猫抓出血怎么办 让狗抓了下红了怎么办 狗咬了一个小口怎么办 小狗咬了出血了怎么办 被小狗咬了出血怎么办 被家养小狗咬了怎么办 狗咬了肿起来了怎么办 被家里猫咬出血怎么办 狗跳蚤会传染人怎么办 猫咪被跳蚤咬了怎么办 被老鼠跳蚤咬了怎么办 猫猫身上有跳蚤怎么办 狗被其他狗咬了怎么办 被土狗咬了出血怎么办 狗咬了有点破皮怎么办 遇到咬人的狗怎么办 自己的狗咬伤了怎么办 被蚂蚁咬了很痒怎么办 家里有蚂蚁怎么办能除根 被虫咬了红肿很痒怎么办 身体被虫子咬痒怎么办 手被乌龟咬破了怎么办 被乌龟咬出血了怎么办 被巴西乌龟咬了怎么办 孩子被乌龟咬了怎么办 如果被乌龟咬了怎么办 宝宝被乌龟咬了怎么办 上高中了偏文怎么办 上高中了很烦该怎么办 螳螂生完孩子后怎么办 小区门禁卡丢了怎么办 开门感应卡坏了怎么办 我的螃蟹生卵了怎么办 剑三账号被冻结怎么办 疤痕留下的红印怎么办 马桶刷子沾屎了怎么办 马桶上水管堵了怎么办 孕妇吃了姑娘果怎么办 出差被领导睡了怎么办 智融财富 跑路了怎么办 秒钱要是跑路了怎么办