数组的partition调整

该博客讨论了如何在已排序数组中通过一次遍历实现左半部分无重复元素且升序排列,同时保持O(N)的时间复杂度和O(1)的额外空间复杂度。文中给出了多种类似问题的表述,如仅包含0、1、2的数组排序,以及按特定规则重新组织包含红、蓝、黄球的数组。博客还包含了相关问题的解决方案代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目】

给定一个有序数组arr,调整arr使得这个数组的左半部分没有重复元素且升序,而不用保证右部分是否有序。

【举例】

arr=[1,2,2,2,3,3,4,5,6,6,7,7,8,8,8,9]
调整后arr=[1,2,3,4,5,6,7,8,9,…]

【补充题目】

给定一个arr,其中只可能含有0,1,2三个值,请实现arr的排序
另一种问法:有一个数组,其中只有红球、篮球和黄球,请事先红球全放在数组的左边,蓝球放中间,黄球放右边。
另一种问法:有一个数组,再给定一个值K,请实现比k小的数都在数组的左边,比K大的都在右边,等于k的都在中间。

【要求】

所有题目的时间复杂度O(N) 额外空间复杂度O(1)

【代码】

public static void main(String[] args) {
        int[] arr={1,2,2,2,3,3,4,5,6,6,7,7,8,8,8,9};
        leftUnique(arr);
        for(int i:arr){
            System.out.print(i);//123456789,6272883
        }
        System.out.println();
        int[] arr1={1,2,2,2,0,0,1,1,2,2,1,2,0,0,0,1};
        leftUnique2(arr1);
        for(int i:arr1){
            System.out.print(i);//00000,11111,222222
        }   
    } 
    //数组的partition调整
        public static void leftUnique2(int[] arr){
            if(arr==null ||arr.length<2){
                return;
            }
            int left=-1;
            int index=0;
            int right=arr.length;
            while(index<right){
                //从左到右遍历各个元素,直到中区和右区接壤
                if(arr[index]==0){
                    //放到左区,交换当前arr[index]与arr[left+1]
                    swap(arr,index++,++left);
                }else if(arr[index]==2){
                    //放到右区,交换当前arr[index]与arr[right-1]
                    //但交换后,arr[index]值未知,故index不变
                    swap(arr,index,--right);
                }else{
                    index++;//放中间,不用交换
                }
            }
        }

    //数组的partition调整
    public static void leftUnique(int[] arr){
        if(arr==null ||arr.length<2){
            return;
        }
        int u=0;//arr[0...u]是保证元素升序且不重复的左部分
        int i = 1;// 从左遍历i,arr[u+1,...i]上是不保证的右部分
        while (i != arr.length) {
            if (arr[i++] != arr[u]) {
                //因为数组整体有序,故主要不等于,就说明arr[i]比arr[u]大
                swap(arr, i - 1, ++u);//将当前arr[i]放到arr[u+1]位置上
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值