912.排序数组(堆排序)
目录
- 题目
- 解法
- 1. 建立最大堆 (buildMaxHeap)
- 从最后一个非叶子节点开始,依次调用 `maxHeapify`:
- 最大堆完成:
- 2. 堆排序过程
- 第一轮:
- 第二轮:
- 第三轮:
- 第四轮:
- 最终排序结果
题目
给你一个整数数组 nums,请你将该数组升序排列。
你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。
解法
class Solution {void buildMaxHeap(vector<int>& nums) {int n = nums.size();for (int i = (n - 1) / 2; i >= 0; --i) {maxHeapify(nums, i, n);}}void maxHeapify(vector<int>& nums, int i, int n) {while (i * 2 + 1 < n) {// 代表当前 i 节点的左右儿子;// 超出数组大小则代表当前 i 节点为叶子节点,不需要移位int lSon = 2 * i + 1;int rSon = 2 * i + 2;int large = i;if (lSon < n && nums[lSon] > nums[i]) large = lSon;if (rSon < n && nums[rSon] > nums[large]) large = rSon;if (large != i) {swap(nums[i], nums[large]);// 迭代判断对应子节点及其儿子节点的大小关系i = large;} else {break;}}}public:vector<int> sortArray(vector<int>& nums) {// heapSort 堆排序int n = nums.size();// 将数组整理成大根堆buildMaxHeap(nums);for (int i = n - 1; i >= 1; --i) {// 依次弹出最大元素,放到数组最后,当前排序对应数组大小 - 1swap(nums[0], nums[i]);--n;maxHeapify(nums, 0, n);}return nums;}
};
让我们用一个具体的例子来展示你提供的堆排序算法的排序过程。我们用数组 nums = [3, 5, 1, 10, 2] 作为示例。
1. 建立最大堆 (buildMaxHeap)
首先,我们需要将数组构建成一个最大堆:
- 初始数组:
[3, 5, 1, 10, 2]
从最后一个非叶子节点开始,依次调用 maxHeapify:
-
对于
i = 1:- 左子节点:
5,右子节点:10 10>5,所以large更新为3(10的索引)。- 交换
nums[1]和nums[3],得到[3, 10, 1, 5, 2]。 - 对于
i = 3,没有子节点,不需要再调整。
- 左子节点:
-
对于
i = 0:- 左子节点:
10,右子节点:1 10>3,所以large更新为1。- 交换
nums[0]和nums[1],得到[10, 3, 1, 5, 2]。 - 现在
i = 1,左子节点为5,右子节点为2。 5>3,更新large为3。- 交换
nums[1]和nums[3],得到[10, 5, 1, 3, 2]。 - 对于
i = 3,没有子节点,不需要再调整。
- 左子节点:
最大堆完成:
最大堆为 [10, 5, 1, 3, 2]。
2. 堆排序过程
现在我们开始排序:
- 初始数组:
[10, 5, 1, 3, 2]
第一轮:
- 交换
nums[0]和nums[4](10 和 2),得到[2, 5, 1, 3, 10]。 - 调用
maxHeapify对i = 0,n = 4:- 左子节点:
5,右子节点:1。 5>2,更新large为1。- 交换,得到
[5, 2, 1, 3, 10]。 - 对于
i = 1,左子节点为3,更新large为3。 - 交换,得到
[5, 3, 1, 2, 10]。
- 左子节点:
第二轮:
- 交换
nums[0]和nums[3](5 和 2),得到[2, 3, 1, 5, 10]。 - 调用
maxHeapify对i = 0,n = 3:- 左子节点:
3,右子节点:1。 3>2,更新large为1。- 交换,得到
[3, 2, 1, 5, 10]。
- 左子节点:
第三轮:
- 交换
nums[0]和nums[2](3 和 1),得到[1, 2, 3, 5, 10]。 - 调用
maxHeapify对i = 0,n = 2:- 左子节点:
2,无右子节点。 2>1,更新large为1。- 交换,得到
[2, 1, 3, 5, 10]。
- 左子节点:
第四轮:
- 交换
nums[0]和nums[1](2 和 1),得到[1, 2, 3, 5, 10]。 - 此时
n = 1,不需要再调用maxHeapify。
最终排序结果
经过上述步骤,最终得到的排序结果为 [1, 2, 3, 5, 10]。
通过这个例子,你可以清楚地看到如何通过最大堆的建立和调整,完成堆排序的过程。
