算法打卡日志-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;
}