https://leetcode.com/problems/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?
解题思路:
开始没看清题意,以为相邻的相同rating,获得candy数量也必须一样。实际上这点没要求。
所以用了下面的方法,从左到右和从右到左分别找出连续最大长度的递增子数列,再将这两者比较,这样就可以确定那个拿到最多candy的顶点了。然后从这个顶点分别向左右扩展,遇到大的+1,相等的不变,小的-1,直到遇到数组两头。但因为题意理解错误,也就无法验证正确性了。
public class Solution { public int candy(int[] ratings) { if(ratings.length == 0){ return 0; } if(ratings.length == 1){ return 1; } int longestPeakIndexUp = 0, longestPeakIndexDown = 0; int longestLengthUp = 1, maxLengthUp = 1, longestLengthDown = 1, maxLengthDown = 1; for(int i = 1; i < ratings.length; i++){ if(ratings[i] > ratings[i - 1]){ longestLengthUp++; if(i == ratings.length - 1){ if(longestLengthUp > maxLengthUp){ maxLengthUp = longestLengthUp; longestPeakIndexUp = i; } } }else{ if(longestLengthUp > maxLengthUp){ maxLengthUp = longestLengthUp; longestPeakIndexUp = i - 1; } longestLengthUp = 1; } } for(int i = ratings.length - 2; i >= 0; i--){ if(ratings[i] > ratings[i + 1]){ longestLengthDown++; if(i == 0){ if(longestLengthDown > maxLengthDown){ maxLengthDown = longestLengthDown; longestPeakIndexDown = i; } } }else{ if(longestLengthDown > maxLengthDown){ maxLengthDown = longestLengthDown; longestPeakIndexDown = i + 1; } longestLengthDown = 1; } } int maxLength = maxLengthUp; int longestPeakIndex = longestPeakIndexUp; if(maxLengthUp < maxLengthDown){ maxLength = maxLengthDown; longestPeakIndex = longestPeakIndexDown; } int candyNumbers = maxLength, thisNumber = maxLength; for(int i = longestPeakIndex + 1; i < ratings.length; i++){ if(ratings[i] > ratings[i - 1]){ thisNumber++; }else if(ratings[i] < ratings[i - 1]){ thisNumber--; } candyNumbers += thisNumber; } thisNumber = maxLength; for(int i = longestPeakIndex - 1; i >= 0; i--){ if(ratings[i] > ratings[i + 1]){ thisNumber++; }else if(ratings[i] < ratings[i + 1]){ thisNumber--; } candyNumbers += thisNumber; } return candyNumbers; } }
发现了错误后,意味着有两个变化。第一,12333321这样的数列,中间的3完全可以全是1。第二,42341这样的数列,num就是21231。注意倒数第二个数字4,它的num来自于左侧较长的递增数列。
理解了题意,代码倒是简单了。首先将默认的num都置为1。然后从左到右递增就+1,不变就置为1。从右到左递增+1,但是如果前面已经赋值了,而且此时的值不如以前大,比如上面的4位置,就不能更新值,否则会打破从左到右的递增。这样的值基本上是左右都是递增的peak。
public class Solution { public int candy(int[] ratings) { int[] num = new int[ratings.length]; if(ratings.length == 0 || ratings.length == 1){ return ratings.length; } for(int i = 0; i < num.length; i++){ num[i] = 1; } //从左到右更新 for(int i = 1; i < ratings.length; i++){ if(ratings[i] > ratings[i - 1]){ num[i] = num[i - 1] + 1; }else if(ratings[i] == ratings[i - 1]){ num[i] = 1; } } //从右到左更新 for(int i = ratings.length - 2; i >= 0; i--){ if(ratings[i] > ratings[i + 1]){ int temp = num[i + 1] + 1; if(temp >= num[i]){ num[i] = temp; } } } int total = 0; for(int i = 0; i < num.length; i++){ total += num[i]; } return total; } }