一、题目描述
给你一个整数数组 nums
,请你将该数组升序排列。
示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]
二、题解
1.快速排序
快速排序,时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间复杂度 O ( log n ) O(\log n) O(logn):
class Solution {
public:
vector<int> sortArray(vector<int> &nums) {
quickSort(nums, 0, nums.size() - 1);
return nums;
}
private:
void quickSort(vector<int> &nums, int begin, int end) {
if (begin < end) {
int pivot = partition(nums, begin, end);
quickSort(nums, begin, pivot - 1);
quickSort(nums, pivot + 1, end);
}
}
int partition(vector<int> &nums, int low, int high) {
int pivot_num = nums.at(low);
while (low < high) {
while (low < high && nums.at(high) >= pivot_num) {
high--;
}
nums.at(low) = nums.at(high);
while (low < high && nums.at(low) <= pivot_num) {
low++;
}
nums.at(high) = nums.at(low);
}
nums.at(low) = pivot_num;
return low;
}
};
2.堆排序
堆排序,时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间复杂度 O ( 1 ) O(1) O(1):
class Solution {
public:
vector<int> sortArray(vector<int> &nums) {
buildMaxHeap(nums);
for (int i = static_cast<int>(nums.size() - 1); i >= 0; i--) {
swap(nums.at(0), nums.at(i));
heapAdjust(nums, 0, i);
}
return nums;
}
private:
/**
* 构建大根堆
*/
void buildMaxHeap(vector<int> &nums) {
for (int i = static_cast<int>(nums.size()) / 2 - 1; i >= 0; i--) {
heapAdjust(nums, i, static_cast<int>(nums.size()));
}
}
/**
* 调整以root为根的二叉树
* @param nums 存储二叉树元素的数组
* @param root 根节点
* @param len 包括根节点在内要调整的元素总数
*/
void heapAdjust(vector<int> &nums, int root, int len) {
int tmp = nums.at(root); // 本轮需要被筛选的值
/* 从root的孩子开始逐层向下调整 */
for (int child = 2 * root + 1; child < len; child = 2 * child + 1) {
/* 选取两个孩子中值较大的那个节点与父节点进行比较 */
if ((child + 1) < len && nums.at(child + 1) > nums.at(child)) {
child++;
}
/* 如果某一个孩子大于当前根节点,则将该孩子换到当前根上
* 否则结束当前层的调整 */
if (nums.at(child) > tmp) {
nums.at(root) = nums.at(child);
root = child; // 提前准备下一层循环
} else {
break;
}
}
/* 将筛选的值放到最终位置上 */
nums.at(root) = tmp;
}
};
3.二路归并排序
二路归并排序,时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间复杂度 O ( n ) O(n) O(n):
class Solution {
public:
vector<int> sortArray(vector<int> &nums) {
supply.reset(new vector<int>(nums.size()));
mergeSort(nums, 0, static_cast<int>(nums.size() - 1));
return nums;
}
private:
void mergeSort(vector<int> &nums, int begin, int end) {
if (begin < end) {
int mid = (begin + end) / 2;
mergeSort(nums, begin, mid);
mergeSort(nums, mid + 1, end);
merge(nums, begin, mid, end);
}
}
/**
* 将两个子数组合并为一个大数组
* @param nums 数据
* @param begin 第一个子数组的起始元素下标
* @param mid 第一个子数组的结束元素下标,它后面一个元素即为第二个子数组的起始元素
* @param end 第二个子数组的结束元素下标
*/
void merge(vector<int> &nums, int begin, int mid, int end) {
int front, back, i;
/* 将数据从nums拷贝到辅助数组中 */
for (i = begin; i <= end; i++) {
supply->at(i) = nums.at(i);
}
/* 依次将两个子数组的最小值复制到大数组中 */
for (front = begin, back = mid + 1, i = begin; front <= mid && back <= end; i++) {
if (supply->at(front) < supply->at(back)) {
nums.at(i) = supply->at(front++);
} else {
nums.at(i) = supply->at(back++);
}
}
/* 处理剩余数据 */
while (front <= mid) {
nums.at(i++) = supply->at(front++);
}
while (back <= end) {
nums.at(i++) = supply->at(back++);
}
}
private:
unique_ptr<vector<int>> supply = nullptr; // 辅助数组
};