持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
每日刷题 2022.06.13
- leetcode原题链接:leetcode.cn/problems/he…
- 难度:简单
- 方法:计数排序
题目
- 学校打算为全体学生拍一张年度纪念照。根据要求,学生需要按照 非递减 的高度顺序排成一行。
- 排序后的高度情况用整数数组 expected 表示,其中 expected[i] 是预计排在这一行中第 i 位的学生的高度(下标从 0 开始)。
- 给你一个整数数组 heights ,表示 当前学生站位 的高度情况。heights[i] 是这一行中第 i 位学生的高度(下标从 0 开始)。
- 返回满足 heights[i] != expected[i] 的 下标数量 。
示例
- 示例1
输入:heights = [1,1,4,2,1,3]
输出:3
解释:
高度:[1,1,4,2,1,3]
预期:[1,1,1,2,3,4]
下标 2 、4 、5 处的学生高度不匹配。
- 示例2
输入:heights = [5,1,2,3,4]
输出:5
解释:
高度:[5,1,2,3,4]
预期:[1,2,3,4,5]
所有下标的对应学生高度都不匹配。
- 示例3
输入: heights = [1,2,3,4,5]
输出: 0
解释:
高度:[1,2,3,4,5]
预期:[1,2,3,4,5]
所有下标的对应学生高度都匹配。
提示
1 <= heights.length <= 1001 <= heights[i] <= 100
解题思路
- 分析题意:按照非递减(递增且可以相等) 的高度排序,
expected[i]和heights[i]都表示这一行中第i位学生的高度,需要返回heights[i] != expected[i]不相等的下标数量。 - 最直观的做法,第一反应就是使用排序函数
sort,将expected排序后和heights中的每一位进行比较,如果遇到不相等的就++,最终返回不相等的数量即可。 - 再深入的想想,如果存在多个
1,但是他们在不同的位置,那么当你排序后,其会回到正确的位置上,那么不管是哪个1在前还是在后都是一样的(因为我们不关心其应该回到哪个位置上,我们只关心有哪些是不在自己的位置上的),因此:本题并不在意排序好后每个元素所在的正确位置,而是在意一共有多少个不同的下标数量,因此可以将思路转到如何求不同的下标数量上。
sort排序
- 书写拷贝字符串的两种方式,可以选择一种自己喜欢的记下来。(可以得到两个完全不相同的字符串,不再是两个变量引用一个地址)
<!-- 拷贝字符串,两个字符串不相等 -->
h = [...heights]
<!-- 上面的更简单,也可以写成如下: -->
h = heights.join(' ').split(' ')
计数排序
- 时间复杂度比
sort排序更小,因此这种做法更优。 - 查看题目的数据范围是
1~100,因此可以开一个长度为101的数组nums来记录:heights数组中每个值出现的次数。 - 循环遍历
nums数组,因为是单调递增的,因此只需要将其和heights数组中的元素一一比较即可,如果不相等,就ans++ - 最后返回结果
ans
AC代码
sort排序:
/**
* @param {number[]} heights
* @return {number}
*/
var heightChecker = function(heights) {
// 排序
// let e = heights.join(' ').split(' ');
let e = [...heights];
e.sort((a, b) => {
return a - b;
});
let ans = 0;
heights.forEach((value, index) => {
ans = ans + (value == e[index] ? 0 : 1);
});
return ans;
};
- 计数排序
/**
* @param {number[]} heights
* @return {number}
*/
var heightChecker = function(heights) {
// 计数排序:因为并不要求我们真正的进行排序,因为不需要确确实实的知道每个位置上排列的是谁,只需要统计下每个数的个数,然后依次判断就可以了
// O(n)的时间复杂度
let num = new Array(101).fill(0), n = heights.length, m = num.length;
heights.forEach(value => num[value]++);
// console.log(num)
let count = 0;
for(let i = 1, j = 0; i < m; i++) {
while(num[i]-- > 0) {
if(heights[j++] != i) count++;
}
}
return count;
};