给定一组数,将其从小到大排序,要求时间复杂度为。
分析比较朴素的归并排序算法,本质思想就是将数组不断折半,最后将数组全部拆分为长度为1或2的子数组,然后进行排序后再合并到一起
解决方法void merge(vector& data, int start, int end) { int mid = start + (end - start) / 2; vector left(mid - start, 0); vector right(end - mid + 1, 0); for (int i = start; i < end; i++) { i < mid ? left.push_back(data[i]) : right.push_back(data[i]); } int i, j = 0; int index = start; while (i < left.size() && j < right.size()) { if (left[i] > right[j]) { data[index++] = right[j++]; } else { data[index++] = left[i++]; } } while (i < left.size()) { data[index++] = left[i++]; } while (j < right.size()) { data[index++] = right[j++]; } } void mergeSort(vector & data, int start, int end) { if (start >= end) { return; } int mid = start + (end - start) / 2; mergeSort(data, start, mid); mergeSort(data, mid + 1, end); merge(data, start, end); }
问题二:逆序对个数 题目描述
给定一个数组,求其中所有的逆序对个数。
分析其实本质上还是进行归并排序,只不过在比较合并的过程中,如果前半个数组中存在某一个值比后半个数组中的值大,需要计数,最后求和即可。
解决方法int merge(vector& data, int start, int end, int sum) { int mid = start + (end - start) / 2; vector left(mid - start, 0); vector right(end - mid + 1, 0); for (int i = start; i < end; i++) { i < mid ? left.push_back(data[i]) : right.push_back(data[i]); } int i, j = 0; int index = start; while (i < left.size() && j < right.size()) { if (left[i] > right[j]) { sum += left.size() - i; data[index++] = right[j++]; } else { data[index++] = left[i++]; } } while (i < left.size()) { data[index++] = left[i++]; } while (j < right.size()) { data[index++] = right[j++]; } return sum; } int mergeSort(vector & data, int start, int end, int sum) { if (start >= end) { return; } int mid = start + (end - start) / 2; sum += mergeSort(data, start, mid, sum); sum += mergeSort(data, mid + 1, end, sum); return merge(data, start, end, sum); }
问题三:快速排序 题目描述
给定一个数组,通过快速排序的方法将数组进行排序。
分析使用最基本的快速排序算法即可实现。(注意双指针的使用以及标准值的确定)
解决方法void quickSort(vectordata, int start, int end) { if (start >= end) { return; } int leftPointer = start; int rightPointer = end + 1; int key = data[start]; while (1) { while (data[++leftPointer] < key) { if (leftPointer == end) { break; } } while (data[--rightPointer] > key) { if (rightPointer == start) { break; } } if (leftPointer >= rightPointer) { break; } swap(data[leftPointer], data[rightPointer]); } data[start] = data[rightPointer]; data[rightPointer] = key; quickSort(data, start, rightPointer - 1); quickSort(data, rightPointer + 1, end); }
问题四:第k大数 问题描述
给定一个数组,找出其中第k大的数。
分析选用不同的排序方法可以以不同的时间复杂度解决该问题
解决方法 冒泡排序int findKthLargestByBubble(vectordata, int k) { bool flag = true; for (int i = 0; i < k && flag; i++) { flag = false; for (int j = data.size() - 2; j >= i; j--) { if (data[j] < data[j + 1]) { swap(data[j], data[j + 1]); flag = true; } } } return data[k - 1]; }
其时间复杂度可以较为容易的判断出,为。
选择排序int findKthLargestBySelection(vectordata, int k) { bool flag = true; for (int i = 0; i < k && flag; i++) { flag = false; for (int j = i + 1; j < data.size(); j++) { if (data[j] > data[i]) { swap(data[j], data[i]); flag = true; } } } return data[k - 1]; }
其时间复杂度与冒泡排序相同。但是这两种排序算法在数据量巨大时(即k和n规模相近),时间复杂度就会变为,计算效率将会大打折扣。
快速排序int findKthLargestByQuickSort(vectordata, int k) { return find(data, 0, data.size(), k); } int find(vector data, int start, int end, int k) { int key = data[start]; int leftPointer = start; int rightPointer = end + 1; while (1) { while (data[++leftPointer] < key) { if (leftPointer == end) { break; } } while (data[--rightPointer] > key) { if (rightPointer == start) { break; } } if (leftPointer >= rightPointer) { break; } swap(data[leftPointer], data[rightPointer]); } data[start] = data[rightPointer]; data[rightPointer] = key; if (rightPointer == k - 1) { return key; } else if (rightPointer > k - 1) { return find(data, start, rightPointer - 1, k); } else { return find(data, rightPointer + 1, end, k); } }
由于最差也只是经过一次对数组的完整搜索,所以其时间复杂度为。
还有其余的排序方法,例如堆排序、归并排序等,其时间复杂度均为。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)