NC140排序
知识点:排序
题目链接
题目描述
给定一个数组,请你编写一个函数,返回该数组排序后的形式。
示例1
输入:[5,2,3,1,4]
返回值:[1,2,3,4,5]
示例2
输入:[5,1,6,2,5]
返回值:[1,2,5,5,6]
备注:
数组的长度不大于100000,数组中每个数的绝对值不超过109
解题思路
快排思想:用到了分治思想,和分治算法一样为了进行排序需要先对其划分的子区间进行排序。
-
基本思想:在待排序的序列中选取一个值作为一个基准值,按照这个基准值得大小将这个序列划分成两个子序列,基准值会在这两个子序列的中间,一边是比基准小的,另一边就是比基准大的。
-
这样快速排序第一次排完,我们选取的这个基准值就会出现在它该出现的位置上。这就是快速排序的单趟算法,也就是完成了一次快速排序。然后再对这两个子序列按照同样的方法进行排序,直到只剩下一个元素或者没有元素的时候就停止,这时候所有的元素都出现在了该出现的位置上。
-
左右指针法实现思路:
-
在一段区间内我们有一个值key(基准),一般会选择数组的头或者尾
-
从右向左边区间进行遍历,直到找到一个大于key的值就停下
-
然后再从右边找小于key的值,找到一个也停下来
-
我们将左右的值进行交换,这样左边那个大于key的值就被换到了右边,而右边那个比key小的值就被换到了左边
-
当左右两个指针相遇的时候就说明所有元素都与key做过了比较。然后再将左指针所在的元素赋值给key
-此时按照上述方法进行递归实现[left, key-1]和[key+1, right]
代码
#include "cheader.h"
class Solution {
public:
vector<int> MySort(vector<int>& arr){
MySort_qsort(arr,0,arr.size()-1);
return arr;
}
//快排 时间复杂度O(logn)。空间复杂度是O(n) 不稳定算法
void MySort_qsort(vector<int>& arr,int left,int right){
if(left >= right)
return ;
int i = left, j = right;
int base = arr[left];//基准假设是第一个值
while(i < j){
//从右往左找 找到比base小的
while(i < j && arr[j] >= base)
j--;
// 从左往右找 找到比base大的
while(i < j && arr[i] <= base)
i++;
swap(arr[i],arr[j]);
}
//把基准值放到该放的位置
swap(arr[i],arr[left]);
MySort_qsort(arr, left, i-1);
MySort_qsort(arr, i+1, right);
}
//堆排序 时间复杂度O(logn)。空间复杂度是O(n) 不稳定算法
void MySort_heapsort(vector<int>& arr){
priority_queue<int,vector<int>,greater<int>> q; //小顶堆
for(int x:arr)
q.push(x);
for(int i = 0; i < arr.size(); i++) {
arr[i] = q.top();
q.pop();
}
}
//归并排序 时间复杂度O(logn)。空间复杂度是O(n) 稳定算法
void mergeSort(vector<int> &arr, int left, int right) {
if(left >= right)
return;
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid); // 递归 左半边
mergeSort(arr, mid+1, right); // 递归 右半边
merge(arr, left, mid, right); // 合并两个有序的数组(参考合并两个有序的链表)
}
void merge(vector<int> &arr, int left, int mid, int right) {
vector<int> tmp(right-left+1); // 开辟新的数组
int i = left, j = mid+1, k = 0; // i左边数组的起始位置,j右边数组的起始位置,k已经放入新数组的个数
while(i <= mid && j <= right){ // 比较左右数组,数值小的放入新数组中
tmp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
}
while(i <= mid)
tmp[k++] = arr[i++]; // 如果左半边数组没有排序完,加入新数组
while(j <= right)
tmp[k++] = arr[j++]; // 如果右半边数组没有排序完,加入新数组
for(i = left, k = 0; i <= right;)
arr[i++] = tmp[k++]; // 新数组数据放回到原来的数组中
}
};
int main()
{
vector<int> arr{5,2,3,1,4};
Solution s;
s.MySort(arr);
for(int x:arr)
cout<<x<<endl;
return 0;
}