各种排序相关题目的实现

来源:互联网 发布:网络语列表是什么意思 编辑:程序博客网 时间:2024/06/15 06:23

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[n];        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_sort

class 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;    }};
0 0
原创粉丝点击