各种排序相关题目的实现
2016-05-16 20:01
295 查看
1. 冒泡排序
循环n次, 每次将最大值交换到最后的一个位置class BubbleSort { public: int* bubbleSort(int* A, int n) { // write code here for (int i = 0; i != n - 1; i++){ for (int j = 0; j != n - i - 1; j++){ if (A[j] > A[j + 1]) swap(A[j], A[j + 1]); } } return A; } };
2. 选择排序
每次从剩余部分中, 挑选出最小的值, 并与相应位置上的数值进行交换class SelectionSort { public: int* selectionSort(int* A, int n) { // write code here for (int i = 0; i != n; i++){ int minid = i; for (int j = i; j != n; j++){ if (A[j] < A[minid]){ minid = j; } } if (minid != i) swap(A[minid], A[i]); } return A; } };
3. 插入排序
每次向已经排序的序列中插入一个值, 保证插入后的数组还是排序的class InsertionSort { public: int* insertionSort(int* A, int n) { // write code here for (int i = 0; i != n; i++){ int tmp = A[i]; for (int j = i - 1; j != -2; j--){ if (j == -1){ A[j + 1] = tmp; continue; } if (A[j] > tmp) A[j + 1] = A[j]; else{ A[j + 1] = tmp; break; } } } return A; } };
4. 归并排序
对两个子数组分别归并排序, 然后对这两个数组合并class MergeSort { public: int* mergeSort(int* A, int n) { // write code here if (n <= 1) return A; int lenA1 = n >> 1, lenA2 = n - (n >> 1); int * A1 = mergeSort(A, lenA1); int * A2 = mergeSort(A + lenA1, lenA2); // merge int * B = new int ; int id1 = 0, id2 = 0, id = 0; while (id1 < lenA1 && id2 < lenA2){ if (A1[id1] < A2[id2]){ B[id++] = A1[id1++]; } else{ B[id++] = A2[id2++]; } } while (id1 < lenA1){ B[id++] = A1[id1++]; } while (id2 < lenA2){ B[id++] = A2[id2++]; } for (int i = 0; i != n; i++){ A[i] = B[i]; } return A; } };
5. 快速排序
先对原数据进行分割, 划分成 比 privot 大的和比 privot 小的部分, 然后对这两个部分分别进行快速排序class QuickSort { public: int* quickSort(int* A, int n) { // write code here if (n <= 1) return A; int tmp = A[0]; int start = 0; int stop = n - 1; while (start < stop){ while (start < stop && A[stop] >= tmp) stop--; if (start < stop) A[start] = A[stop]; while (start < stop && A[start] < tmp) start++; if (start < stop) A[stop] = A[start]; } A[stop] = tmp; quickSort(A, stop); quickSort(A + stop + 1, n - stop - 1); return A; } };
6. 堆排序
建立一个堆, 然后对堆依次做调整class HeapSort { public: int* heapSort(int* A, int n) { // write code here for (int i = n - 1; i != -1; i--){ modify(A, i); swap(A[i], A[0]); } return A; } private: void modify(int * A, int n){ for (int i = n; i != -1; i--){ if (A[i] > A[i / 2]) swap(A[i], A[i / 2]); } } };
7. 希尔排序
实际上就是步长因子不断减小的插入排序class ShellSort { public: int* shellSort(int* A, int n) { // write code here for (int gap = n / 2; gap > 0; gap /= 2){ // insert sort for (int i = gap; i != n; i++){ int tmp = A[i]; for (int j = i - gap; j >= -gap; j -= gap){ if (j < 0){ A[j + gap] = tmp; continue; } if (A[j] > tmp){ A[j + gap] = A[j]; } else{ A[j + gap] = tmp; break; } } } } return A; } };
8. 计数排序
计算元素出现的次数, 然后排序class CountingSort { public: int* countingSort(int* A, int n) { // write code here int mymax = INT_MIN, mymin = INT_MAX; for (int i = 0; i != n; i++){ if (mymax < A[i]) mymax = A[i]; if (mymin > A[i]) mymin = A[i]; } int size = mymax - mymin + 1; int * B = new int[size]; memset(B, 0, size * sizeof(int)); for (int i = 0; i != n; i++) B[A[i] - mymin]++; int id = 0; for (int i = 0; i != size; i++){ for (int j = 0; j != B[i]; j++){ A[id++] = i + mymin; } } return A; } };
9. 基数排序
基数排序内部需要用到一个稳定的排序算法, 这里偷懒, 直接使用了STL 的 stable_sortclass RadixSort{ public: int* radixSort(int* A, int n) { // write code here using namespace std::placeholders; vector<int> arr(A, A + n); int mymax = *max_element(arr.begin(), arr.end()); int N = 0; while (mymax){ mymax /= 10; N++; } cout << N << endl; for (int i = 0; i != N; i++){ stable_sort(arr.begin(), arr.end(), bind(cmp, _1, _2, i)); for_each(arr.begin(), arr.end(), [](int a){cout << a << " "; }); cout << endl; } for (int i = 0; i != n; i++) A[i] = arr[i]; return A; } private: static bool cmp(int a, int b, int id){ int aa = int(a / pow(10, id)) % 10; int bb = int(b / pow(10, id)) % 10; return aa < bb; } };
10. 小范围排序
实际上是堆排序的一种应用/* 已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。 给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。 */ class ScaleSort { public: vector<int> sortElement(vector<int> A, int n, int k) { // write code here vector<int> myheap(A.begin(), A.begin() + k); buildHeap(myheap, k); for (int i = 0; i != n - k; i++){ A[i] = myheap[0]; myheap[0] = A[i + k]; modifyHeap(myheap, k, 0); } for (int i = 0; i != k; i++){ A[i + n - k] = myheap[0]; myheap[0] = myheap[k - 1 - i]; modifyHeap(myheap, k - i, 0); } return A; } private: void buildHeap(vector<int> & myheap, int k){ for (int i = k / 2; i >= 0; i--){ modifyHeap(myheap, k, i); } } void modifyHeap(vector<int> & myheap, int k, int pos){ while (true){ int targetid = 2 * pos + 1; if (targetid >= k) break; if (2 * pos + 2 < k && myheap[targetid] > myheap[2 * pos + 2]){ targetid = 2 * pos + 2; } if (myheap[pos] < myheap[targetid]) break; swap(myheap[targetid], myheap[pos]); pos = targetid; } } // // 递归版本的modifyHeap // void modifyHeap(vector<int> & myheap, int k, int pos){ // int targetid = 2 * pos + 1; // if (targetid >= k) // return; // // if (2 * pos + 2 < k && myheap[targetid] > myheap[2 * pos + 2]){ // targetid = 2 * pos + 2; // } // // if (myheap[pos] < myheap[targetid]) // return; // // swap(myheap[targetid], myheap[pos]); // modifyHeap(myheap, k, targetid); // } };
11. 重复值判断
/* 请设计一个高效算法,判断数组中是否有重复值。必须保证额外空间复杂度为O(1)。 给定一个int数组A及它的大小n,请返回它是否有重复值。 */ class Checker { public: bool checkDuplicate(vector<int> & a, int n) { // write code here buildHeap(a, n); for (int i = 0; i != n; i++){ swap(a[n - i - 1], a[0]); modifyHeap(a, n - i - 1, 0); } for (int i = 0; i != n; i++){ if (i > 0 && a[i - 1] == a[i]) return true; } return false; } private: void buildHeap(vector<int> & myheap, int k){ for (int i = k / 2; i >= 0; i--){ modifyHeap(myheap, k, i); } } void modifyHeap(vector<int> & myheap, int k, int pos){ while (true){ int targetid = 2 * pos + 1; if (targetid >= k) break; if (2 * pos + 2 < k && myheap[targetid] > myheap[2 * pos + 2]){ targetid = 2 * pos + 2; } if (myheap[pos] < myheap[targetid]) break; swap(myheap[targetid], myheap[pos]); pos = targetid; } } };
12. 有序数合并
从数组的尾部开始操作/* 有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。请编写一个方法,将B合并入A并排序。 给定两个有序int数组A和B,A中的缓冲空用0填充,同时给定A和B的真实大小int n和int m,请返回合并后的数组。 */ class Merge { public: int* mergeAB(int* A, int* B, int n, int m) { // write code here int ia = n - 1, ib = m - 1, id = n + m - 1; while (ib >= 0){ if (ia >= 0){ if (A[ia] >= B[ib]) A[id--] = A[ia--]; else A[id--] = B[ib--]; } else A[id--] = B[ib--]; } return A; } };
13. 三色排序
荷兰国旗问题, 三个指针区分三个数据范围{0}{1}{2}class ThreeColor { public: vector<int> sortThreeColor(vector<int> A, int n) { // write code here int low = 0, high = n - 1, cur = 0; while (cur <= high){ if (A[cur] == 1) cur++; else if (A[cur] == 0){ if (cur != low) swap(A[cur], A[low]); cur++; low++; } else if (A[cur] == 2){ swap(A[cur], A[high]); high--; } } return A; } };
14. 有序矩阵查找
典型的杨氏矩阵查找问题, 从左上角入手/* 现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。 给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x,请返回一个bool值,代表矩阵中是否存在x。所有矩阵中数字及x均为int范围内整数。保证n和m均小于等于1000。 */ class Finder { public: bool findX(vector<vector<int> > mat, int n, int m, int x) { // write code here int i = 0, j = m - 1; while (true){ if (i >= n || j < 0) return false; if (mat[i][j] == x) return true; else if (mat[i][j] > x) j--; else i++; } return false; } };
15. 最短子数组
从左边开始找第一个下降的项位置, 从右边开始找第一个上升的项的位置/* 对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。(原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。 */ class Subsequence { public: int shortestSubsequence(vector<int> A, int n) { // write code here int left = 0, right = 1; int mymax; for (int i = 0; i != n; i++){ if (i == 0){ mymax = A[0]; } else{ if (mymax <= A[i]){ mymax = A[i]; } else{ left = i; } } } int mymin; for (int i = n - 1; i != -1; i--){ if (i == n - 1){ mymin = A[n - 1]; } else{ if (mymin >= A[i]){ mymin = A[i]; } else{ right = i; } } } return left - right + 1; } };
16. 相邻两数最大差值
利用桶排序的思想 (鸽巢原理)/* 有一个整形数组A,请设计一个复杂度为O(n)的算法,算出排序后相邻两数的最大差值。 给定一个int数组A和A的大小n,请返回最大的差值。保证数组元素多于1个。 */ class Gap { public: int maxGap(vector<int> A, int n) { // write code here int mymax = INT_MIN, mymin = INT_MAX; for (int i = 0; i != n; i++){ if (A[i] > mymax) mymax = A[i]; if (A[i] < mymin) mymin = A[i]; } double gap = (mymax - mymin + 0.001) * 1.0 / (n + 1); vector<vector<int>> bucks(n + 1, vector<int>{INT_MIN, INT_MAX, 0}); for (int i = 0; i != n; i++){ int id = (A[i] - mymin) / gap; bucks[id][0] = max(bucks[id][0], A[i]); bucks[id][1] = min(bucks[id][1], A[i]); bucks[id][2]++; } int maxgap = 0; int id = 0; while (id < n){ while (!bucks[id][2]) id++; int low = bucks[id][0]; id++; while (!bucks[id][2]) id++; int high = bucks[id][1]; int tmp = high - low; maxgap = max(maxgap, tmp); } return maxgap; } };
相关文章推荐
- 网络攻防平台基础第一关
- CVPR 2013 录用论文(目标跟踪部分)
- 设计模式之桥接模式
- java发送地址(url)如何隐藏.action
- 使用boost.asio时遇到的一个小问题
- ARP协议
- 使用autoconf和automake生成Makefile文件
- 马云,王健林,马化腾是否是社会主义的合理存在?
- C# 虚方法
- Java---基于TCP协议的相互即时通讯小程序
- 第十一周【项目4- 教师兼干部类】
- 用logrotate管理每日增长的日志
- linux关于readlink函数获取运行路径的小程序
- Java---基于TCP协议的相互即时通讯小程序
- boost---shared_ptr笔记
- CSDN Latex 一些数学符号
- Python - 两圆相交求交点坐标
- kill -HUP pid
- MacOS虚拟机安装VMware tools 在主机与虚拟机之间共享文件和剪贴板
- JFrame中设置背景图片