前言
虽然是介绍递归形式的快速排序, 但是做题时都用的C++ STL的sort(),面试时可得手写啊。
快速排序
递归形式详解:快速排序C语言实现
原理
每次找到基准值,以基准值为分界线,左边的值全部比基准值小,右边的值全部比基准值大。
规则
- 从右向左找比基准值小的数据,找到后放到左边;
- 从左向右找比基准值大的数据,找到后放到右边;
- 重复 1、2操作,如果 left == right (下标),循环退出,再将基准值放到nums[left]或nums[right]。
代码实现
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
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<string>& 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:
vector<int> sortedSquares(vector<int>& nums)
{
int n = nums.size();
for (int i = 0; i < n; ++i)
{
nums[i] *= nums[i];
}
sort(nums.begin(), nums.end(), less<int>());
return nums;
}
};
870. 优势洗牌
原题链接:870. 优势洗牌
分析
将A、B排序,每次取A B中未使用的最大值进行比较。
但要知道哪个元素未使用,需要记住每个元素的下标。
这里就需要利用C++的 pair
pair可以将 2个数据 组合成 一组数据,两个数据可以分别用pair的 两个公有函数 first 和 second访问。
代码
将nums1和打包后的nums2按照从大到小排序
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2)
{
int n = nums1.size();
vector<pair<int, int>> sorted(n);
for (int i = 0; i < sorted.size(); ++i)
{
sorted[i] = {nums2[i], i};
}
sort(nums1.begin(), nums1.end(), greater<int>());
sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b){return a.first > b.first;});
vector<int> 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. 救生艇
原题链接:881. 救生艇
分析
先对所有人的体重进行排序;
那可以以这种方式来做:
首先排除最重的人比救生艇的承重还要重。。。
- 如果最轻的人和最重的人体重加起来不超过救生艇的承重,那就可以把他们两个放在一个救生艇上,然后排除这两个人,再从剩下的人里按照这样的方法来;
- 如果超过了承重,那就让最重的人独自乘坐一条救生艇,在之后分配时不考虑此人。
实现:
在排序后,利用两个指针,一个指向最轻的人,一个指向最重的,按照上面的方式,遇到情况1,将首指针++, 尾指针–;遇到情况2,只将尾指针-- 。
代码
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit)
{
sort(people.begin(), people.end(), less<int>());
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;
}
};
end
原文链接:《算法零基础100讲》(第37讲) 排序进阶 - 快速排序
作者:英雄哪里出来
谢谢大家收看~