分发糖果(leetcode135)

分发糖果

135. 分发糖果

本题算得上是一个十分有难度的题了。首先逻辑上就不是很好想怎么解决这个问题。这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼

此处先给出判断流程:

  • 先从左往右遍历,从第二个节点开始,比较当前节点和前一个节点的大小。如果比前一个节点大,则在前一个节点的糖果数量上+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;
    }
}

406. 根据身高重建队列

本题和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][]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值