Easy
题目描述
学校打算为全体学生拍一张年度纪念照。为此,要求学生们按照 非递减 的高度顺序排成一行。
排列后的高度情况用整数数组 expected 表示,其中 expected[i] 是预期排在这一位置的学生的高度。
给你一个整数数组 heights,表示 当前学生站位 的高度情况。heights[i] 是第 i 位学生的高度(下标从 0 开始)。
返回满足 heights[i] != expected[i] 的 下标数量。
示例 1:
输入:heights = [1,1,4,2,1,3]
输出:3
解释:
heights: [1,1,4,2,1,3]
expected: [1,1,1,2,3,4]
下标 2、4、5 上的学生高度不匹配。
示例 2:
输入:heights = [5,1,2,3,4]
输出:5
解释:
heights: [5,1,2,3,4]
expected: [1,2,3,4,5]
所有下标的对应学生高度都不匹配。
示例 3:
输入:heights = [1,2,3,4,5]
输出:0
解释:
heights: [1,2,3,4,5]
expected: [1,2,3,4,5]
所有下标的对应学生高度都匹配。
提示:
1 <= heights.length <= 1001 <= heights[i] <= 100
解题思路
解题思路
这道题的核心思想是比较当前学生的排列顺序与正确的排列顺序之间的差异。
方法一:排序比较法(推荐) 最直观的解法是将原数组排序得到期望的顺序,然后逐一比较对应位置的元素。具体步骤:
- 复制原数组并排序,得到期望的高度顺序
- 遍历原数组,比较每个位置的实际高度与期望高度
- 统计不匹配的位置数量
方法二:计数排序优化 由于题目限制了高度范围(1-100),我们可以使用计数排序的思想来优化:
- 统计每个高度出现的次数
- 根据计数信息重构期望数组
- 比较原数组和期望数组的差异
两种方法时间复杂度相同,但计数排序在某些情况下常数因子更小。对于这道题的数据规模,排序比较法更加直观易懂,是推荐的解法。
代码实现
class Solution {
public:
int heightChecker(vector<int>& heights) {
vector<int> expected = heights;
sort(expected.begin(), expected.end());
int count = 0;
for (int i = 0; i < heights.size(); i++) {
if (heights[i] != expected[i]) {
count++;
}
}
return count;
}
};
class Solution:
def heightChecker(self, heights: List[int]) -> int:
expected = sorted(heights)
count = 0
for i in range(len(heights)):
if heights[i] != expected[i]:
count += 1
return count
public class Solution {
public int HeightChecker(int[] heights) {
int[] expected = new int[heights.Length];
Array.Copy(heights, expected, heights.Length);
Array.Sort(expected);
int count = 0;
for (int i = 0; i < heights.Length; i++) {
if (heights[i] != expected[i]) {
count++;
}
}
return count;
}
}
var heightChecker = function(heights) {
const expected = [...heights].sort((a, b) => a - b);
let count = 0;
for (let i = 0; i < heights.length; i++) {
if (heights[i] !== expected[i]) {
count++;
}
}
return count;
};
复杂度分析
| 复杂度类型 | 排序比较法 |
|---|---|
| 时间复杂度 | O(n log n) |
| 空间复杂度 | O(n) |
说明:
- 时间复杂度:主要由排序操作决定,为 O(n log n),其中 n 是数组长度
- 空间复杂度:需要额外的数组存储排序后的结果,为 O(n)