算法打卡日志-2020.11.16 | LeetCode406

题目:406.根据身高重建队列

这道题的标签是贪心算法,不是很熟悉,所以略有不解,花了点时间,最终想了一个解法:

先用排序算法将数据从小到大排序,再依次由小到大,将数据填入新的数组中,填入的思路是:每个数据(h)的k对应这个数据前有k=m个空+n个h。m是用于后续填充比h大的数,预留出来,题目的条件中临界值包含等于,所以除了m之外,还要有n=k-m个等于h的位置。
这样填入数据可以得到结果的关键就是由小到大填入,因为后填的数据一定比先填的要大,所以只要确保在h前预留k个空位,就一定可以满足题目。

这种思路没有问题,但是有一个小细节忽略了,就是h是否为零的问题,原先以为身高不应该为零,结果还是被坑了。所以在排序时顺便将res数据初始化为-999,并将判断为空的条件由0变为-999。

此解法的时间复杂度为O(n 2 )、空间复杂度O(n),都较大。

优化思路:选择排序时,不进行实际的排序操作,而是将选择出的最小值直接插入res数组中理论上可以减少时间。

public int[][] reconstructQueue(int[][] people) {
    int len = people.length;
    int[][] res = new int[len][2];
	//选择排序,将数据按从小到大排序
    for (int i = 0; i < len; i++) {
        res[i][0]=-999;//将数组初始化为-999
        int[] min = people[i];
        for (int j = i; j < len; j++) {
            if (people[j][0] < min[0]) {
                int[] tmp = people[j];
                people[j] = min;
                min = tmp;
            //添加额外的判断,若h相同,则比较k,k较小者为小数;不存在h k都相同的情况
            } else if (people[j][0] == min[0]) {
                if (people[j][1] < min[1]) {
                    int[] tmp1 = people[j];
                    people[j] = min;
                    min = tmp1;
                }
            }
        }
        people[i] = min;
    }
    for (int i = 0; i < len; i++) {
        int flag = -1;
        for (int j = 0; j < len; j++) {
            if (res[j][0] == people[i][0]) {
                flag++;
            } else if (res[j][0] == -999) {//条件由0改为-999
                flag++;
            }
            if (flag == people[i][1]) {
                res[j] = people[i];
                break;
            }
        }
    }
    return res;
}
posted @ 2020-11-17 20:16  PPPPu  阅读(67)  评论(0)    收藏  举报