theory into practice. 实现各类排序方法
插入排序: 直接插入排序、折半插入排序、希尔排序 交换排序:冒泡排序、快速排序 选择排序:简单选择排序、堆排序 归并排序 基数排序
归并排序
JZ51 数组中的逆序对 解题思路:一开始使用的是两重for循环嵌套,结果5/6测试用例通过。后看到题目要求时间复杂度为
o
(
n
log
?
n
)
o(n\log n)
o(nlogn),需要对进行改进。 首先备份一下两重for循环的代码:
class Solution {
public:
int InversePairs(vector<int> data) {
int p = 0;
for(vector<int>::iterator it1 = data.begin(); it1 != data.end(); it1++)
{
for(vector<int>::iterator it2 = it1 + 1; it2 != data.end(); it2++)
{
if(*it2 < *it1) p++;
}
}
return p % 1000000007;
}
};
接下来是改进方法:采用归并排序,分而治之。 思路:
- 递归划分到最小操作区间
- 合并,将两个操作区间合并为一个区间【用临时数组存储】,然后将临时数组赋值给最初的数组
class Solution {
public:
long cnt;
int InversePairs(vector<int> data)
{
cnt = 0;
if(data.size() == 0) return 0;
mergesort(data,0,data.size() - 1);
return cnt % 1000000007;
}
void mergesort(vector<int>& A, int low, int high)
{
if(low < high)
{
int mid = (low + high) / 2;
mergesort(A,low,mid);
mergesort(A,mid+1,high);
vector<int> tmp;
merge(A,tmp,low,mid,high);
}
}
void merge(vector<int>& A,vector<int> B,int low,int mid,int high)
{
int i, j;
for(i = low, j = mid + 1; i <= mid && j <= high;)
{
if(A[i] > A[j])
{
B.push_back(A[j++]);
cnt += mid - i + 1;
}
else if(A[i] <= A[j]) B.push_back(A[i++]);
}
while(i <= mid) B.push_back(A[i++]);
while(j <= high) B.push_back(A[j++]);
int k = 0;
for(int i = low; i <= high && k < B.size(); i++)
{
A[i] = B[k++];
}
}
};
难点
vector<int>tmp 的位置,按照算法笔记的介绍来说,用来存储暂时的合并结果的数组应该在merge() 函数之外 解决方法: 加在mergesort() 函数体内,递归划分到最小操作区间之后,开始merge之前- 计数器
cnt 的使用 解决方法: 归并排序的“精髓”就是两个有序的区间合并为一个有序的区间,即:两个数组A,B ,若A[i] < B[j] ,则A[0], A[1] ... A[i-1] 均小于B[j] 。所以可用来求逆序对,若A[i]>B[j] ,则有一个逆序对,cnt+1 - “临时”向量的使用,
tmp 作为一个储存临时结果的容器,整个归并排序的过程需要的是这个容器,而不是容器里的内容,因此在参数传递中,不需要使用引用,即void merge(vector<int>& A,vector<int> B,int low,int mid,int high) ,A需要加引用,因为是源数据,而B不需要加引用
堆排序(优先队列)
首先,放上堆排序的代码
void BuildMaxHeap(int A[],int len)
{
for(int i = len / 2; i > 0; i--)
HeadAdjust(A,i,len);
}
void HeadAdjust(int A[],int k, int len)
{
A[0] = A[k];
for(int i = 2 * k; i <= len; i *= 2)
{
if(i < len && A[i]<A[i+1]) i++;
if(A[0] >= A[i]) break;
else
{
A[k] = A[i];
k = i;
}
}
A[k] = A[0];
}
void HeapSort(int A[], int len)
{
BuildMaxHeap(A,len);
for(int i = len; i > 1; i--)
{
swap(A[i],A[1]);
HeadAdjust(A,1,i-1);
}
}
然后,是本质是堆排序的优先队列 语法见STL总结,注意:top可返回堆顶,而pop只能删除,无法得到删除的数据 具体应用:JZ40 最小的K个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
vector<int> ans;
if(k == 0 || k > input.size()) return ans;
priority_queue<int,vector<int>> pri_que;
for(const int val : input)
{
if(pri_que.size() < k) pri_que.push(val);
else
{
if(val < pri_que.top())
{
pri_que.pop();
pri_que.push(val);
}
}
}
while(!pri_que.empty())
{
ans.push_back(pri_que.top());
pri_que.pop();
}
return ans;
}
};
C++中sort()函数
语法见STL总结 具体应用:JZ40 最小的K个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
vector<int> ans;
if(k == 0 || k > input.size()) return ans;
sort(input.begin(),input.end());
for(int i = 0; i < k; i++)
ans.push_back(input[i]);
return ans;
}
};
快速排序
首先,放上算法
void QuickSort(ElemType A[], int low, int high)
{
if(low < high)
{
int pivotpos = Partition(A, low, high);
QuickSort(A, low, pivotpos - 1);
QuickSort(A, pivotpos + 1, high);
}
}
int Partition(ElemType A[], int low, int high)
{
ElemType pivot = A[low];
while(low < high)
{
while(low < high && A[high] >= pivot) --high;
A[low] = A[high];
while(low < high && A[low] <= pivot) ++low;
A[high] = A[low];
}
A[low] = pivot;
return low;
}
具体应用:JZ40 最小的K个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
vector<int> ans;
if(k == 0 || k > input.size()) return ans;
QuickSort(input, 0, input.size()-1);
for(int i = 0; i < k; i++)
ans.push_back(input[i]);
return ans;
}
void QuickSort(vector<int>& data,int low, int high)
{
if(low < high)
{
int pivotpos = Partition(data,low,high);
QuickSort(data, low, pivotpos - 1);
QuickSort(data, pivotpos + 1, high);
}
}
int Partition(vector<int>&data,int low, int high)
{
int pivot = data[low];
while(low < high)
{
while(low < high && data[high] >= pivot) high--;
data[low] = data[high];
while(low < high && data[low] <= pivot) low++;
data[high] = data[low];
}
data[low] = pivot;
return low;
}
};
|