leetcode hard模式专杀之135. Candy
2017-08-06 15:31
288 查看
这题大概思路出来大概十来分钟,不过做到通过oj却花了几个小时,主要是一些情况没有考虑完整,首先在纸上画一划,看看如果人去做这件事,会怎么做,画了几遍之后,可以得出一个大概都结论,例如ratings序列是[1,2,3,7,5,6,9,2,1],首先第一个位置的孩子得到1个糖果,rating值等于5的孩子得到1个糖果, 然后最后一个孩子得到一个糖果,然后其他位置的孩子,从这几个位置推导出来即可,那么两个问题来了, 第一,这三个位置如何得到呢?如果把这个几个值连一条曲线,会发现这几个点都在local minimum的位置,所以只要先找出每个localMinum的位置,这些位置的孩子就可以确定得到1个糖果,计算localMinimum位置时,注意一串相等的数字的情况,例如【5,4,4,4,4,6】这么一串数字,第一个4毫无疑问是localMin,那么第二个4计算的时候只要看到前一个4已经是localMin,就不需要再做运算了,直接可以判定为也是localMin,这样可以节约计算时间,然后再逐个想办法,把每两个localMinimum之间的数字填充正确,别忘了开头和结尾两个位置的特殊情况。第二个问题是,填充的原则是什么。两个localMininum之间可能有几种情况,例如假设给定两个点1,1,要在这两个数之间填充比1大的数字,可能出现三种情况,单调递增,如【2,3,4】,单调递减,如【5,4,3】,先递增后递减【3,5,4】,还有可能出现有连续相同数字的情况【3,4,4,5】,【3,4,5,5,4】等等。怎么统一处理呢?想到一种思路,对所有localminimum切割成的一段段位置,分别做如下处理:两个循环,第一个从左端点开始一路向右遍历,直到不再递增(相等也算递增吧),第二个同样反过来从右端点一路向左遍历,直到不再递增,遍历的时候这样设值:如果大于前一个数q,则设置为q处count值+1或这该位置已有值二者之间的大者,为什么是这样,可以假设有两个localMin位置之间是这样一个序列1,3,8,7,6,5,4,1,8这个位置如果从左往右看,需要该位置的糖果值是3,
而如果从右往左看,需要的糖果数是6,到底选3还是选6呢?当然是选大的,也就是6才行。如果等于前一个数字,则在1和该位置已有值之间去大者,为什么会是跟1比?因为如果有3,4,4,4,3这样一个序列,则中间这个4这个位置的值完全可以设为1,也就是我们可以设计一种原则,只要跟前一个数比rating值相等,则这个位置可以先试着放1,除非从另一侧的遍历时要求这个位置有更大的值(这也是为什么要用max函数的原因)。思路大概如此,代码如下:
而如果从右往左看,需要的糖果数是6,到底选3还是选6呢?当然是选大的,也就是6才行。如果等于前一个数字,则在1和该位置已有值之间去大者,为什么会是跟1比?因为如果有3,4,4,4,3这样一个序列,则中间这个4这个位置的值完全可以设为1,也就是我们可以设计一种原则,只要跟前一个数比rating值相等,则这个位置可以先试着放1,除非从另一侧的遍历时要求这个位置有更大的值(这也是为什么要用max函数的原因)。思路大概如此,代码如下:
public class Solution { public static void setNeighbour(int[] ratings, int[] counts, int start, int end) { int len = ratings.length; if(end-start<=1) { return; } if(end-start==2) { counts[start+1]=2; }else { //left to right int i = start+1; while(i<=len-1 && (i==0 || ratings[i]>=ratings[i-1])) { if(i==0) { counts[0] = 1; }else { if(ratings[i]>ratings[i-1]) { counts[i]=Math.max(counts[i], counts[i-1]+1); }else { //equal counts[i]=Math.max(counts[i], 1); } } i++; } //right to left int j = end-1; while(j>=0 && (j==len-1 || ratings[j]>=ratings[j+1])) { if(j==len-1) { counts[j]=1; }else { if(ratings[j]>ratings[j+1]) { counts[j]=Math.max(counts[j+1]+1,counts[j]); }else { //equal counts[j] = Math.max(counts[j], 1); } } j--; } } } public static boolean localMin(int[] ratings, int index) { boolean leftBigger = false; boolean rightBigger = false; int len = ratings.length; int i = index - 1; while(i>=0 && ratings[i]==ratings[index]) { i--; } if(i<0) { leftBigger = true; }else if(ratings[i] > ratings[index]) { leftBigger = true; } int j = index + 1; while(j < len && ratings[j]==ratings[index]) { j++; } if(j>=len) { rightBigger = true; }else if(ratings[j]>ratings[index]) { rightBigger = true; } return leftBigger && rightBigger; } public int candy(int[] ratings) { int len = ratings.length; BitSet bs = new BitSet(); boolean leftBigger = true; for(int i = 0 ; i < len; i++) { if(i>0 && ratings[i] == ratings[i-1] &&bs.get(i-1)) { bs.set(i); }else if(localMin(ratings, i)) { bs.set(i); } } System.out.println("Input is:" + Arrays.toString(ratings)); System.out.println("Bit set is:" + bs); int[] counts = new int[len]; //set counts start int prevLocalMinPos = -1; for(int i = 0; i< bs.length(); i++) { if(bs.get(i)) { counts[i] = 1; setNeighbour(ratings, counts, prevLocalMinPos, i); prevLocalMinPos = i; } } if(prevLocalMinPos < len-1) { for(int i = prevLocalMinPos+1; i< len; i++) { if(ratings[i]>ratings[i-1]) { counts[i] = counts[i-1]+1; }else { // equals counts[i] = 1; } } } //set counts end int result = 0; for(int i = 0 ; i<counts.length; i++) { result += counts[i]; } System.out.println("Counts is:" + Arrays.toString(counts)); return result; } }
相关文章推荐
- leetcode hard模式专杀之45. Jump Game II
- leetcode hard模式专杀之32. Longest Valid Parentheses
- leetcode hard模式专杀之37. Sudoku Solver
- leetcode hard模式专杀之57. Insert Interval
- leetcode hard模式专杀之52 N-Queens II
- leetcode hard模式专杀之23 merge k sorted lists
- leetcodehard 模式专杀之85. Maximal Rectangle
- leetcode hard模式专杀之68. Text Justification
- leetcode hard模式专杀之233. Number of Digit One
- leetcode hard模式专杀之76 Minimum Window Substring
- leetcode hard模式专杀之10Regular Expression Matching
- leetcode hard模式专杀之55. Jump Game
- leetcode hard模式专杀之51. N-Queens
- leetcode hard模式专杀之99. Recover Binary Search Tree
- leetcode hard模式专杀之295. Find Median from Data Stream
- leetcode hard模式专杀之25 Reverse Nodes in k-Group
- leetcode hard模式专杀之72. Edit Distance
- leetcode hard模式专杀之42. Trapping Rain Water
- leetcode hard模式专杀之41 First Missing Positive
- 设计模式与泡mm的关系之Adapter适配器模式及适配器模式的再思考