虽然是介绍递归形式的快速排序, 但是做题时都用的C++ STL的sort(),面试时可得手写啊。
目录- 前言
- 快速排序
- 原理
- 规则
- 代码实现
- 习题
- 539. 最小时间差
- 分析
- 代码
- 977. 有序数组的平方
- 分析
- 代码
- 870. 优势洗牌
- 分析
- 代码
- 881. 救生艇
- 分析
- 代码
- end
递归形式详解:快速排序C语言实现
原理每次找到基准值,以基准值为分界线,左边的值全部比基准值小,右边的值全部比基准值大。
规则- 从右向左找比基准值小的数据,找到后放到左边;
- 从左向右找比基准值大的数据,找到后放到右边;
- 重复 1、2 *** 作,如果 left == right (下标),循环退出,再将基准值放到nums[left]或nums[right]。
#include#include #include static void Quick(int* nums, int left, int right); static int Partition(int* nums, int left, int right); void Quick_Sort(int* nums, int numsSize) { assert(nums != NULL); Quick(nums, 0, numsSize - 1); } static void Quick(int* nums, int left, int right) { if (left < right) { int par = Partition(nums, left, right); if (left < par - 1) { Quick(nums, left, par - 1); } if (par + 1 < right) { Quick(nums, par + 1, right); } } } static int Partition(int* nums, int left, int right) { int key = nums[left]; //重复三个规则 while (left < right) { while (left < right && nums[right] > key) right--; if (left == right) { break; } nums[left] = nums[right]; while (left < right && nums[left] < key) left++; if (left == right) { break; } nums[right] = nums[left]; } nums[left] = key; //nums[right] = key return left; //return right }
详细过程可看上面链接的文章。。
习题 539. 最小时间差原题链接:539. 最小时间差
分析做法是
- 先申请一个等长的整型数组;
- 将原字符串数组中的串依次转为整数存放在新的数组中;
- 遍历新数组,找出最小时间差;
- 遍历后得出的最小答案,再考虑 00:00 和23:59的情况。
class Solution { public: int findMinDifference(vector& timePoints) { int n = timePoints.size(); //1 int timeArray[n]; memset(timeArray, 0, sizeof(timeArray)); //2 for (int i = 0; i < n; ++i) { timeArray[i] = stoi(timePoints[i].substr(0, 2)) * 60 + stoi(timePoints[i].substr(3, 2)); } //3 sort(timeArray, timeArray + n); int ans = 1440, tmp = 1440; for (int i = 0; i < n - 1; ++i) { tmp = timeArray[i + 1] - timeArray[i]; ans = min(tmp, ans); } //4 int err = 24 * 60 + timeArray[0] - timeArray[n - 1]; return min(ans, err); } };
对应的四个步骤,很容易理解。。
977. 有序数组的平方原题链接:977. 有序数组的平方
分析先依次平方,再排序
代码class Solution { public: vector870. 优势洗牌sortedSquares(vector & nums) { int n = nums.size(); for (int i = 0; i < n; ++i) { nums[i] *= nums[i]; } sort(nums.begin(), nums.end(), less ()); return nums; } };
原题链接:870. 优势洗牌
分析将A、B排序,每次取A B中未使用的最大值进行比较。
但要知道哪个元素未使用,需要记住每个元素的下标。
这里就需要利用C++的 pair
pair可以将 2个数据 组合成 一组数据,两个数据可以分别用pair的 两个公有函数 first 和 second访问。
代码将nums1和打包后的nums2按照从大到小排序
class Solution { public: vector881. 救生艇advantageCount(vector & nums1, vector & nums2) { int n = nums1.size(); vector > sorted(n); for (int i = 0; i < sorted.size(); ++i) { sorted[i] = {nums2[i], i}; } sort(nums1.begin(), nums1.end(), greater ()); sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b){return a.first > b.first;}); vector ans(n); int left = 0, right = n - 1; for (int i = 0; i < n; ++i) { auto[cur, index] = sorted[i]; if (nums1[left] <= cur) { ans[index] = nums1[right--]; } else { ans[index] = nums1[left++]; } } return ans; } };
原题链接:881. 救生艇
分析先对所有人的体重进行排序;
那可以以这种方式来做:
首先排除最重的人比救生艇的承重还要重。。。
- 如果最轻的人和最重的人体重加起来不超过救生艇的承重,那就可以把他们两个放在一个救生艇上,然后排除这两个人,再从剩下的人里按照这样的方法来;
- 如果超过了承重,那就让最重的人独自乘坐一条救生艇,在之后分配时不考虑此人。
实现:
在排序后,利用两个指针,一个指向最轻的人,一个指向最重的,按照上面的方式,遇到情况1,将首指针++, 尾指针–;遇到情况2,只将尾指针-- 。
class Solution { public: int numRescueBoats(vectorend& people, int limit) { sort(people.begin(), people.end(), less ()); int ans = 0; int light = 0, heavy = people.size() - 1; while (light <= heavy) { if (people[light] + people[heavy] > limit) { --heavy; } else { ++light; --heavy; } ++ans; } return ans; } };
原文链接:《算法零基础100讲》(第37讲) 排序进阶 - 快速排序
作者:英雄哪里出来
谢谢大家收看~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)