荷兰国旗问题
题目
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
示例 3:
输入:nums = [0]
输出:[0]
示例 4:
输入:nums = [1]
输出:[1]
思路
这是一个典型的双指针问题,由题意可知,我们最后需要将数组分成三部分, [0···,1···, 2···]
由此,我们定义两个int类型的整数 p1,p2 。p1指向数组的第一个元素,p2指向数组的最后一个元素,分别代表数组三部分的边界,在代码运行的过程中,边界逐渐向中心移动,移动的过程中同时对数组进行元素交换(排序)。
定义一个数组指针index,指向数组的第一个元素,开始遍历。
- 遍历结束标志,index <= p2(到达右边界时停止)
- 如果index指向的元素小于1(即为0),那么就需要将该元素移动到数组的左部分,这时候,将index指向的元素与p1指向的元素交换即可,然后p1++(左边界向右扩),index++(p1原来指向的元素是小于等于1的)。
- 如果index指向的元素等于1,那么index++即可,边界不用动。
- 如果index指向的元素大于1(即为2),那么就需要将该元素移动到数组的右部分,这时候,将index指向的元素与p2指向的元素交换即可,然后p2–(右边界向左扩),index不动(p2原来指向的元素是大于等于1的,index++后会跳过p2原来指向的元素)。
代码
void sortColors(vector<int>& nums)
{
int p1 = 0;
int p2 = nums.size()-1;
int index = p1;
while(index <= p2)
{
if(nums[index] < 1)
{
swap(nums[p1++], nums[index++]);
}
else if(nums[index] == 1)
{
index++;
}
else
{
swap(nums[p2--], nums[index]);
}
}
}
快速排序
思想
快速排序和荷兰国旗问题很相似
它是把一个数字先排到相应的位置,然后把比这个数小的元素和大的元素分开,不断递归
比如,我们有这样一组数
23 | 46 | 0 | 8 | 11 | 18 |
---|
我们先把最后一个数(18)先排好,得到
8 | 0 | 11 | 18 | 46 | 23 |
---|
我们会发现,比18小的数都排到了左边,比18大的数都拍到了右边
然后我们就得到3组数,(8,0,11)(18)(46,23)
数字18的位置以及排好了,然后去排左边和右边的一组数,同理,左边会得到3组数,右边会得到3组数(有一组数是空的),就这么循环下去,所有的数都排好了
我们会发现,快排的关键是将一个数字排好并把比它大的数和比它小的数分开,我们就可以利用荷兰国旗问题的思想,利用双指针就可以把数排好
代码实现
#include <algorithm>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <cstring>
using namespace std;
int arr[100005];
int n;
vector<int> mar(int left, int right);
void quickSort(int left, int right)
{
if (left >= right - 1)
return;
int mid = (rand()%(right - left)) + left;
swap(arr[mid], arr[right - 1]);
vector<int> nums = mar(left, right);
quickSort(left, nums[0]);
quickSort(nums[1], right);
}
vector<int> mar(int left, int right)
{
int num = arr[right - 1];
int index = left;
int p1 = left;
int p2 = right;
while (index < p2)
{
if (arr[index] < num)
swap(arr[index++], arr[p1++]);
else if (arr[index] > num)
swap(arr[index], arr[--p2]);
else
++index;
}
return { p1,p2 };
}
int main()
{
srand((unsigned)time(NULL));
memset(arr, 0x00, sizeof(arr));
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
}
quickSort(0, n);
for (int i = 0; i < n; ++i)
{
cout << arr[i] << " ";
}
return 0;
}
本文题目来自LeetCode
https://leetcode-cn.com/problems/sort-colors/