这道题就是给数组进行排序,下面用三种排序方法来解决这道题。
1. 快速排序。
思想:设置两个指针,一个low和一个high,每次取出当前数组的第一个节点作为privot,然后与指针high进行比较,直到不满足,那么将该值交换到low所在的位置;接着与low比较,直到不满足,那么交换该值到high所在位置。
最后找到privot在数组中所在的位置,接着递归比较前半部分和后半部分。
可以产生一个随机种子来作为privot,优化速度,但是本题还是超时了。所以写了一个判断数组是否有序的函数来判断(没错,面向用例编程)。
class Solution {
public:
void quickSort(vector<int> & nums, int begin, int end){
if(begin >= end) return;
int l = begin, h = end;
//产生一个随机种子
int i = rand() % (h - l + 1) + l;
swap(nums[l], nums[i]);
int privot = nums[l];
while(l < h){
while(l < h && nums[h] >= privot) h--;
nums[l] = nums[h];
while(l < h && nums[l] <= privot) l++;
nums[h] = nums[l];
}
nums[l] = privot;
quickSort(nums, begin, l);
quickSort(nums, l+1, end);
}
static bool comp(int i, int j) {
return i < j;
}
vector<int> sortArray(vector<int>& nums) {
bool flag = false;
for(int i=1; i < nums.size(); i++){
if(nums[i] < nums[i-1]){
flag = true;
break;
}
}
if(!flag)
return nums;
srand((unsigned)time(NULL));
quickSort(nums, 0, nums.size()-1);
return nums;
}
};
2. 堆排序。
堆排序思想:
先建堆,本题建立的是大顶堆,也就是升序排序。从数组的中点开始调整堆,使得每个父节点都比它的左右子节点要大。建完堆之后,每次取出根节点(也就是最大的节点),取出的元素放置在数组的最后,然后重新从根节点开始调整堆。
void heapify(vector<int>& nums, int i, int n){
int lson = (i << 1) + 1;
int rson = (i << 1) + 2;
int large = 0;
if(lson <= n && nums[lson] > nums[i])
large = lson;
else
large = i;
if(rson <= n && nums[rson] > nums[large])
large = rson;
//该节点需要做调整
if(large != i){
swap(nums[i], nums[large]);
heapify(nums, large, n);
}
}
void buildMaxheap(vector<int>& nums, int n){
for(int i = n >> 1; i>=0; i--){
heapify(nums, i, n);
}
}
void heapSort(vector<int> &nums){
int n = nums.size();
//建一个大顶堆
buildMaxheap(nums, n-1);
for(int i = n-1; i > 0; i--){
//每次将堆顶的数字交换到最后一个位置
swap(nums[0], nums[i]);
n--;
//交换之后需要重新调整堆
heapify(nums, 0, n-1);
}
}
3. 归并排序。
思想:需要声明临时的数组,每次都对数组进行对半分割,然后比较前半部分和后半部分,将较小值存入临时数组。最后再将有序的部分存入原数组对应的位置。
void mergeSort(vector<int>& nums, vector<int>& temp, int left, int right){
if(left >= right) return;
int mid = (left + right) >> 1;
mergeSort(nums, temp, left, mid);
mergeSort(nums, temp, mid+1, right);
int i = left, j = mid+1, k = 0;
while(i <= mid && j <= right){
temp[k++] = nums[i] <= nums[j] ? nums[i++] : nums[j++];
}
while(i <= mid){
temp[k++] = nums[i++];
}
while(j <= right){
temp[k++] = nums[j++];
}
for(int p = 0; p < k; p++){
nums[left + p] = temp[p];
}
}