[计数排序] 1051. 高度检查器

137 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

每日刷题 2022.06.13

题目

  • 学校打算为全体学生拍一张年度纪念照。根据要求,学生需要按照 非递减 的高度顺序排成一行。
  • 排序后的高度情况用整数数组 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 <= 100
  • 1 <= 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;
};