【题目】
给定一个有序数组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]位置上
}
}
}