每天两道LeetCodeHard:(23)

104 阅读2分钟

135. 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?

解释:

这个题理解起来其实也很简单,就是有一排小孩,需要发糖,满足两个要求: 1,所有小孩都要有糖 2,比邻居分数高的小孩的糖必须更多

思考:

这个题的两个条件其实可以翻译一下,第一个条件是,局部分数最低的小孩的糖数为1,局部分数最低其实就是小于两个邻居的小孩,一次遍历即可找到所有的这样最低点。第二个条件,分数比邻居高的小孩的糖数必须是左右邻居中最大值加一的数额。因此我们只要初始化一个一维的dp数组,遍历每个起点,找到满足以上条件的最小值,然后把每个位置的最小值都加起来即可得到全局最小值。击败27.41% 感觉只要不是用的经典算法,而是按照业务逻辑去写,一般复杂度都会比经典算法高

答案:

class Solution(object):
    def candy(self, ratings):
        """
        :type ratings: List[int]
        :rtype: int
        """
        #遍历数组找到所有的source点
        if len(ratings)==1:
            return 1
        dp=[1]*len(ratings)
        sources=[]
        for i in range(0,len(ratings)):
            if i ==0:
                if ratings[0]<=ratings[1]:
                    sources.append(0)
                    continue
            elif i ==len(ratings)-1:
                if ratings[i]<=ratings[i-1]:
                    sources.append(i)
                    continue
            elif ratings[i]<=ratings[i-1] and ratings[i]<=ratings[i+1]:
                sources.append(i)
        for source in sources:
            self.helperLeft(dp,source,ratings)
            self.helperRight(dp,source,ratings)
        return sum(dp)
    def helperLeft(self,dp,source,ratings):
        if source-1<0:
            return
        if ratings[source-1]<=ratings[source]:
            return
        dp[source-1]=max(dp[source]+1,dp[source-1])
        self.helperLeft(dp,source-1,ratings)
        return
    def helperRight(self,dp,source,ratings):
        if source+1>=len(ratings):
            return
        if ratings[source+1]<=ratings[source]:
            return
        dp[source+1]=max(dp[source]+1,dp[source+1])
        self.helperRight(dp,source+1,ratings)
        return

答案补充:

也可以用两次遍历的写法,第一次从前往后,第二次从后往前。我这个写法实际上是遍历了每个点两遍才找到所有的谷点。