OJ中常用的功能函数(顺序数)
2014-08-15 00:22
211 查看
1.找第 i 顺序数
最佳算法的最坏、平均时间复杂度为:O(n),但是理论较难且实现起来也很复杂,故不介绍。
快选择算法的平均复杂度为O(n)(虽然最坏为O(n^2),但是发生概率极小),并且实现简单,所以用起来很方便。
思想:借用归并排序的Partition函数,分界元素是第几大已知,并且左边是小的右边是大的,因此将问题分而治之。
int Partition(vector<int> &v, int p, int r)
{
int x = v[r];//选取最后一个元素作为参照
int i = p - 1, j = p;
for(; j < r; j++)
{
if(v[j] <= x)
{
i++;
swap(v[j], v[i]);
}
}
swap(v[r], v[i+1]);
return i+1;
}
int QuickSelect(vector<int> &v, int p, int r, int m)
{
int q, result;
q = Partition(v, p, r);
if( q == m - 1)//因为数组是从0开始的
return v[q];
else if(m < q)
result = QuickSelect(v, p, q - 1, m);
else
result = QuickSelect(v, q + 1, r, m);
return result;
}
2.堆排序
主要是为了在找最大k个数中需要用到堆得建立于调整,所以在此介绍堆排序。
//调整最大堆,root为要调整的子树的根,n为当前堆大小
void MaxHeapify(vector<int> &v, int n, int root)
{
int lchild = 2 * (root + 1) - 1, rchild = 2 * (root + 1), largest; //此处数组从下标0开始,不需要从1开始
if(lchild < n && v[root] < v[lchild])
largest = lchild;
else
largest = root;
if(rchild < n && v[largest] < v[rchild])
largest = rchild;
if(largest != root) //根、左儿子和右儿子三者之间的最大者 和 根互换即可
{
swap(v[largest], v[root]);
MaxHeapify(v, n, largest);
}
}
//建最大堆
void BuildMaxHeap(vector<int> &v, int root)
{
int lchild = 2 * (root + 1) - 1, rchild = 2 * (root + 1);
if(lchild < v.size())
BuildMaxHeap(v, lchild); //建左子树
if(rchild < v.size())
BuildMaxHeap(v, rchild); //建右子树
MaxHeapify(v, v.size(), root); //调整最大堆
}
//堆排序
void HeapSort(vector<int> &v)
{
BuildMaxHeap(v, 0); //建堆
int n = v.size();
while(n--)
{
swap(v[0], v
); //将最大元素移到最后
MaxHeapify(v, n, 0); //将未排序部分调整为最大堆
}
}
3.找最小的k个数
(1)思路1:基于堆的,建k个元素的最大堆,然后对剩余的元素依次与根比较,若是比根小就替换根,然后进行堆调整,否则什么都不做,最后堆里的元素就是那最小的k个数,时间复杂度为O(nlogk)。
(2)思路2:建n个元素的最小堆,然后输出k次最小值,比较次数是2n + 2klgn,时间复杂度为O(n + klogn)。缺点是空间复杂度较高,需要O(n)。
(3)思路3:利用锦标赛树。比较次数可以为n + (k - 1)[lgn] - k。在此就不介绍了。
(4)思路1的代码:
最佳算法的最坏、平均时间复杂度为:O(n),但是理论较难且实现起来也很复杂,故不介绍。
快选择算法的平均复杂度为O(n)(虽然最坏为O(n^2),但是发生概率极小),并且实现简单,所以用起来很方便。
思想:借用归并排序的Partition函数,分界元素是第几大已知,并且左边是小的右边是大的,因此将问题分而治之。
int Partition(vector<int> &v, int p, int r)
{
int x = v[r];//选取最后一个元素作为参照
int i = p - 1, j = p;
for(; j < r; j++)
{
if(v[j] <= x)
{
i++;
swap(v[j], v[i]);
}
}
swap(v[r], v[i+1]);
return i+1;
}
int QuickSelect(vector<int> &v, int p, int r, int m)
{
int q, result;
q = Partition(v, p, r);
if( q == m - 1)//因为数组是从0开始的
return v[q];
else if(m < q)
result = QuickSelect(v, p, q - 1, m);
else
result = QuickSelect(v, q + 1, r, m);
return result;
}
2.堆排序
主要是为了在找最大k个数中需要用到堆得建立于调整,所以在此介绍堆排序。
//调整最大堆,root为要调整的子树的根,n为当前堆大小
void MaxHeapify(vector<int> &v, int n, int root)
{
int lchild = 2 * (root + 1) - 1, rchild = 2 * (root + 1), largest; //此处数组从下标0开始,不需要从1开始
if(lchild < n && v[root] < v[lchild])
largest = lchild;
else
largest = root;
if(rchild < n && v[largest] < v[rchild])
largest = rchild;
if(largest != root) //根、左儿子和右儿子三者之间的最大者 和 根互换即可
{
swap(v[largest], v[root]);
MaxHeapify(v, n, largest);
}
}
//建最大堆
void BuildMaxHeap(vector<int> &v, int root)
{
int lchild = 2 * (root + 1) - 1, rchild = 2 * (root + 1);
if(lchild < v.size())
BuildMaxHeap(v, lchild); //建左子树
if(rchild < v.size())
BuildMaxHeap(v, rchild); //建右子树
MaxHeapify(v, v.size(), root); //调整最大堆
}
//堆排序
void HeapSort(vector<int> &v)
{
BuildMaxHeap(v, 0); //建堆
int n = v.size();
while(n--)
{
swap(v[0], v
); //将最大元素移到最后
MaxHeapify(v, n, 0); //将未排序部分调整为最大堆
}
}
3.找最小的k个数
(1)思路1:基于堆的,建k个元素的最大堆,然后对剩余的元素依次与根比较,若是比根小就替换根,然后进行堆调整,否则什么都不做,最后堆里的元素就是那最小的k个数,时间复杂度为O(nlogk)。
(2)思路2:建n个元素的最小堆,然后输出k次最小值,比较次数是2n + 2klgn,时间复杂度为O(n + klogn)。缺点是空间复杂度较高,需要O(n)。
(3)思路3:利用锦标赛树。比较次数可以为n + (k - 1)[lgn] - k。在此就不介绍了。
(4)思路1的代码:
//建最大堆,将前n个元素建堆 void BuildMaxHeap(vector<int> &v, int n, int root) { int lchild = 2 * (root + 1) - 1, rchild = 2 * (root + 1); if(lchild < n) BuildMaxHeap(v, n, lchild); if(rchild < n) BuildMaxHeap(v, n, rchild); MaxHeapify(v, n, root); } void SelectKMin(vector<int> &v, int k) //v的前k个元素就是结果 { BuildMaxHeap(v, k, 0); int i; for(i = k; i < v.size(); i++) { if(v[i] < v[0]) { swap(v[0], v[i]); MaxHeapify(v, k, 0); } } }
相关文章推荐
- MFC中一些常用函数调用顺序及功能
- OJ中常用的功能函数(排序)
- Oracle常用功能(函数)集锦
- Oracle 最常用功能函数经典汇总 (zz)
- arx常用的一些函数功能表
- 一些常用的PHP功能函数(一)-- 消息窗口
- 一些常用的JS功能函数(二)(2009-04-24更新)
- Oracle 最常用功能函数经典汇总
- arx常用的一些函数功能表 【转】
- .net常用功能函数说明
- .net常用功能函数说明
- 一些常用的JS功能函数(2009-06-04更新)
- 我在开发过程总结的一套实现常用功能的函数
- 图形化编程常用函数功能介绍
- JavaScript常用功能函数
- 第10章 常用功能及函数集;客户端IP地址
- oracle 常用功能函数汇总
- Javascript常用功能函数
- 常用文件操作功能函数
- DOM常用功能及常用函数介绍