左神基础班03、颜色分类(荷兰国旗问题)

题目描述:

     给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例1:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

原题链接:颜色分类

解题思路:

1、快速排序 :

      可以利用快速排序中划分的思想,数组arr[L,R]划分后达到的效果为:arr[L,less] < target;arr[less + 1,more - 1] == target,arr[more,R] > target。在这道题中target = 1。设当前元素为arr[cur],cur初始化为L,less初始化为L - 1,more初始化为R + 1,具体的划分过程为:

(1)当arr[cur] < target时,交换arr[++less]和arr[cur++];

(2)当arr[cur] == target时,cur++;

(3)当arr[cur] > target时,交换arr[–more]和arr[cur]。

划分终止条件:cur == more,划分完成。

注:(1)以上的操作没有考虑不存在target的情况,因此在这道题中target存在且为1。

时间复杂度和空间复杂度: 时间复杂度为O(N),空间复杂度为O(1)

实现代码:

class Solution {
    public void sortColors(int[] nums) {
        if(nums == null || nums.length < 2)
            return;
        partition(nums, 0, nums.length - 1);
    }
    public int[] partition(int[] nums, int L, int R){
        if(L < R){
            int less = L - 1;//左边界
            int more = R + 1;//右边界
            int cur = L;
            while(cur < more){
                if(nums[cur] < 1)
                    swap(nums, ++less, cur++);
                else if(nums[cur] == 1)
                    cur++;
                else
                    swap(nums, --more, cur);
            }
        }
        //返回arr[less + 1,more - 1]为target = 1的区间
        return new int[]{less + 1, more - 1};
    }
    public void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

	//这里顺便放上快速排序的写法:
	//1、这种快排是基于随机快排和基于荷兰国旗问题的改进后的快排)
	//2、基于荷兰国旗问题改进后的快排在会一次性将所有相等的数划分到相应的位置,这相对于经典快排中每次只划分一个数的做法速度会相对快一点
	public void quickSort(int[] nums) {
        if(nums == null || nums.length < 2)
            return;
        quickSort(nums, 0, nums.length - 1);
    }
    public void quickSort(int[] nums, int L, int R){
        if(L < R){
            swap(nums, R, (int)(L + Math.random() * (R - L + 1)));//随机选择一个数与数组最后的数交换
            int[] p = partition1(nums, L, R);
            quickSort(nums, L, p[0] - 1);
            quickSort(nums, p[1] + 1, R);
        }
    }

    public int[] partition1(int[] nums, int L, int R){
        int less = L - 1;//左边界
        int more = R;//右边界(先不对nums[R]操作)
        int cur = L;
        while(cur < more){
            if(nums[cur] < nums[R])
                swap(nums, ++less, cur++);
            else if(nums[cur] == nums[R])
                cur++;
            else
                swap(nums, --more, cur);
        }
        swap(nums, more, R);//将nums[R]和nums[more]交换,这样中间区间为nums[less + 1, more]
        return new int[]{less + 1, more}; 
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值