分发糖果
本题算得上是一个十分有难度的题了。首先逻辑上就不是很好想怎么解决这个问题。这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。
此处先给出判断流程:
-
先从左往右遍历,从第二个节点开始,比较当前节点和前一个节点的大小。如果比前一个节点大,则在前一个节点的糖果数量上+1,否则,直接将该节点的糖果数量置为1。此时保证了右侧比左侧大(小)的情况,但是不能保证左侧比右侧大的情况。
例如:
ratings = [1,2,2,5,4,3,2]
,经历过从左到右的遍历后candyNum = [1,2,1,2,1,1,1]
,此时显然不是我们要求的最终结果。 -
再从右往左判断,从倒数第二个位置开始,比较当前节点和后一个节点的大小。如果当前节点大,则让当前节点等于max(当前节点,后一节点加1)。
此时,
candyNum = [1,2,1,4,2,3,1]
,因为前一步已经判断过右侧大于左侧的情况了,所以此时不用再判断左侧小于右侧的情况。
class Solution { public int candy(int[] ratings) { //从前往后遍历一遍,再从后往前遍历一遍,就可以确定最终的值 int[] candyNum = new int[ratings.length]; //从前往后 candyNum[0] = 1; for (int i = 1; i < ratings.length; i++) { if (ratings[i] > ratings[i-1]) { candyNum[i] = candyNum[i-1] + 1; }else { candyNum[i] = 1; } } //从后往前 for (int i = ratings.length-2; i >= 0; i--) { if (ratings[i] > ratings[i+1]) { candyNum[i] = Math.max(candyNum[i+1] + 1,candyNum[i]); } } int sum = 0; for (int i : candyNum) { sum += i; } return sum; } }
本题和135. 分发糖果的解题思路是比较类似的,同样有两个维度上的条件要进行判断。我们不能同时判断两个,只能先把其中一个排好序,再在此基础上对第二个维度排序。
闹我们应该先排hi还是ki?我们可以试一下,发现如果先排ki的话,其实两个维度都没有排好,只有先把hi按降序排好才能定好一个维度。
例如:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
,对身高排序后:people = [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]
然后再对第二个维度ki进行排序,比如[6,1],就把这个人插入到索引为1的位置,就可以保证复核题目条件
-
[[7,0]]
-
[[7,0],[7,1]]
-
[[7,0],[6,1],[7,1]]
-
[[5,0],[7,0],[6,1],[7,1]]
-
[[5,0],[7,0],[5,2],[6,1],[7,1]]
-
[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
至此,得出题目所需答案,因为我们提前对身高排过序了,后面的人一定比前面的人个子矮,所以插到前面不会影响到前面元素的ki的判断。
但是这样的出来的答案就一定正确吗?
大家可以试一试people = [[9,0],[7,0],[1,9],[3,0],[2,7],[5,3],[6,0],[3,4],[6,2],[5,2]]
的情况
正确答案应该是[[3,0],[6,0],[7,0],[5,2],[3,4],[5,3],[6,2],[2,7],[9,0],[1,9]]
但是实际得出的答案为[[3,0],[6,0],[7,0],[5,2],[3,4],[6,2],[5,3],[2,7],[9,0],[1,9]]
根本的原因是:我们在对第一维度排序的时候,没有考虑当第一维度相等的情况下,第二维度的前后顺序。
比如题目中的[5,3]和[5,2]按照题目要求,应该是按照第二维度的升序来排的,我们直接使用了他们在原数组中的顺序进行排列,所以导致的错误。
所以第一次排序的整体逻辑应该是按照身高降序排列,如果身高相等,则按照ki的降序排列。我们用lambda表达式来实现:
Arrays.sort(people,(a,b)->{ //if (a[0] == b[0])return a[1] - b[1];//身高相同的情况下,ki是升序排列 return b[0] - a[0];//身高降序排列 });
第二次排序,我们是直接将元素插入指定位置,使用List比较合适。
List<int[]> res = new ArrayList<>(); for (int[] person : people) { res.add(person[1], person); }
整体代码为
class Solution { public int[][] reconstructQueue(int[][] people) { List<int[]> res = new ArrayList<>(); //先对身高进行排序(降序 Arrays.sort(people,(a,b)->{ //if (a[0] == b[0])return a[1] - b[1];//身高相同的情况下,ki是升序排列 return b[0] - a[0];//身高降序排列 }); for (int[] person : people) { res.add(person[1], person);//往索引为person[1]的位置插入值person } return res.toArray(new int[people.length][]); } }