荷兰国旗问题与快速排序

荷兰国旗问题

题目

给定一个包含红色、白色和蓝色,一共 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]);
            }
        }
    }

快速排序

思想

快速排序和荷兰国旗问题很相似
它是把一个数字先排到相应的位置,然后把比这个数小的元素和大的元素分开,不断递归
比如,我们有这样一组数

2346081118

我们先把最后一个数(18)先排好,得到

8011184623

我们会发现,比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/

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值