LeetCode 135. 分发糖果
解题思路和代码
我们可以举一个比样例稍微好一点的例子[7,8,4,2,1,3,5,9,7]
。
首先可以想到第一种思路:
- 我们先定义一个数组candies,这个数组存放着每个人最终获得的糖果。
- 接着我们找到数组的最小值及其下标定义为sym。如果是第一次遍历,则直接令candies[sym]=1,因为每一位小朋友至少要有一个糖果。在例子中这个最小值是1,sym=4
- 然后我们利用快速排序的思想,最小值的两边分别递归再次寻找最小值。即
[7,8,4,2]
和[3,5,9,7]
再次寻找最小值,以此类推。获得最小值之后,和左右两边比较一下,如果左边或者右边的的candies数组值不为0,则自身的candies数组值为candies[sym]=max(candies[sym],candies[sym-1]+1,candies[sym+1])。当然这里我们假设sym-1
和sym+1
的值都是合法的。
但是这种方法的时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),最后三个数据过不了,超时了。那么有没有 O ( n ) O(n) O(n)的方法呢,答案是有的
class Solution:
def dfs(self, ratings, apples, st, ed):
if st > ed:
return
mmin = 0x7fffffff
sym = 0
for index in range(st, ed+1):
if ratings[index] < mmin:
mmin = ratings[index]
sym = index
if apples[sym] == 0:
apples[sym] += 1
if (sym-1) >= 0:
# if mmin == ratings[sym-1]:
# apples[sym] = max(apples[sym], apples[sym-1])
if mmin > ratings[sym-1]:
apples[sym] = max(apples[sym], apples[sym-1]+1)
if (sym+1) < len(ratings):
# if mmin == ratings[sym+1] and apples[sym+1] != 0:
# apples[sym] = max(apples[sym], apples[sym+1])
if mmin > ratings[sym+1]:
apples[sym] = max(apples[sym], apples[sym+1]+1)
if (sym-1) >= 0:
self.dfs(ratings, apples, st, sym-1)
if (sym+1) < len(ratings):
self.dfs(ratings, apples, sym+1, ed)
def candy(self, ratings):
"""
:type ratings: List[int]
:rtype: int
"""
apples = []
for index in range(len(ratings)):
apples.append(0)
self.dfs(ratings, apples, 0, len(ratings)-1)
ans = 0
for index, number in enumerate(apples):
ans += number
return ans
第二种思路:
我观察了一下数组,发现8这个点为什么它的糖果为4,那是因为后面有四个数比他小啊,那是不是可以利用逆序数的思想呢?
- 首先我们先定义两个数组left和right,left就是从左到右,按照正序的顺序。对于我们的例子来说,最终得到的left数组为
[1,2,1,1,1,2,3,4,1]
。right就是从右到左,按照逆序的顺序,最终的到的数组为[1,4,3,2,1,1,1,2,1]
。 - 最后我们遍历同时遍历一遍right数组和left数组,第i个位置的candies[i]=max(left[i],right[i])
这个算法的时间复杂度就是 O ( n ) O(n) O(n),该算法虽然能过但是时间花的好像还是挺久的,各位大佬们如果有更好的算法欢迎交流,不喜勿喷。
class Solution:
def deal(self,ratings):
left = [0 for i in range(len(ratings))]
right = [0 for i in range(len(ratings))]
for index, number in enumerate(ratings):
if index == 0:
left[index] = 1
else:
if number > ratings[index-1]:
left[index] = left[index-1]+1
else:
left[index] = 1
for index in range(len(ratings)-1, -1, -1):
if index == len(ratings)-1:
right[index] = 1
else:
if ratings[index] > ratings[index+1]:
right[index] = right[index+1]+1
else:
right[index] = 1
ans = 0
for index in range(len(left)):
ans += max(left[index], right[index])
return ans
def candy(self, ratings):
"""
:type ratings: List[int]
:rtype: int
"""
return self.deal(ratings)