声明:
个人原创,如有错误和不足,敬请指正,转载请注明出处
题目描述
某学校举行运动会,学生们按编号(1、2、3...n)进行标识,现需要按照身高由低到高排列, 对身高相同的人,按体重由轻到重排列;对于身高体重都相同的人,维持原有的编号顺序关系。请输出排列后的学生编号。
输出描述
排列结果,每个数值都是原始序列中的学生编号,编号从1开始
示例
* 输入: 4
100 100 120 130
40 30 60 50
* 输出:
* 2 1 3 4
思路
此题考查的是排序算法,本题很容易想到使用插入排序,当然冒泡排序或者其他排序算法也可以,这里我使用了插入排序
插入排序算法的思想是:
* 1、分两个队列,一个队列是待排序的项,另一个队列是已排序的项,
* 2、从未排序队列中取出一项(不放回,取最后一项,取哪项随意),在已排序的队列中查找到合适的位置(前一项身高小于或等于当前项,
* 如果查找的项与当前项身高体重都相同,则继续查找,后一项身高大于或等于当前项(不能同时相同)
* 3、重复以上步骤,直到未排序队列清空
针对此题,给出如下代码:
var n = 5;
var heights = [100,100,120,130,90]
var weights = [40,30,60,50,100]
getRankNums(n,heights,weights)
function getRankNums(n,heights,weights) {// n为人数
let res = [];
// 将两个数组合并一下
let arr = [];
for(let i=0;i<n;i++) {
arr.push([heights[i],weights[i]])
}
// 清空队列
while(arr.length) {
let item = arr.pop();
// 默认插入位置设置为尾部,因为在下面的遍历中,如果到遍历到最后一个依旧没找到插入的位置,则直接将元素项添加到尾部即可
let index = res.length;
for(let i=0; i< res.length; i++) {
if(res[i][0] > item[0]) { // 待排项身高小于已排项,此时的位置即为插入位置,记录并跳出循环
index = i;
break;
}else {
if(res[i][0] < item[0]) { // 待排项身高大于已排项,继续向后查找
continue;
}else { // 只剩下身高相等的情况了,比较体重
if(res[i][1] <= item[1]) { // 如果待排项体重依旧大于等于当前对比项,继续
continue;
}else { // 只剩下这种情况,待排项身高与对比项相同,体重比对比项小,此时的位置即为插入位置,记录并跳出循环
index = i;
break;
}
}
}
}
res.splice(index, 0, item)
}
console.log(res,'res')
return res;
}
时间复杂度和空间复杂度分析
/**
* 最后进行一下时间复杂度分析:上面代码中第一层循环为人数n,第二重循环为已排序人数(0-n),均值为n/2,
* 查找次数期望为n/2,所用总的平均复杂度为n^2/2,因此平均时间复杂度为O(n^2)
* 空间复杂度,我们借用了两个等同于人数的数组,为2n,所以空间复杂度为O(n)
* **/