荷兰国旗问题
给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)
1.分析
- 使用less指针指向给定数组区间的左边的前一个位置 使用more指针指向此区间右侧的后一个位置 使用cur指针指向当前元素
- 若cur的值小于num,则将cur的值与less+1位置的值交换,并将储存小于num值的左侧范围向右加一,cur也向后移动一位;
- 若cur的值大于num,则将cur的值与more-1位置的值交换,并将储存大于num值的右侧范围向左减一,因为交换过来的值与num的关系不确定,因此cur(此时cur的值已经是交换的more-1位置的值)不移动,而是继续判断cur的值与num的关系;
- 相等时cur直接后移。
- 终止条件是:cur和more相遇。
2.Java代码
import java.util.Arrays;
/**
* 荷兰国旗问题,把数组中小于num的放左边,等于的放中间,大于的放右边
*/
public class Partition {
public static void partition(int[] arr, int L, int R, int num) {
int less = L - 1;
int more = R + 1;
int cur = L;
while (cur < more) { //当cur和more相遇时终止
if (arr[cur] < num) {
swap(arr, cur, less + 1); //交换cur位置的值和less+1位置的值
cur++;
less++;
}else if (arr[cur] > num) { //交换cur位置的值和more-1位置的值
swap(arr, cur, more - 1);
more--;
}else { //arr[cur] == num
cur++; //相等时直接下一位
}
}
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = new int[]{1,5,6,5,0};
System.out.println(Arrays.toString(arr));
partition(arr,0,arr.length - 1, 5);
System.out.println(Arrays.toString(arr));
}
}
3.测试用例和结果
[1, 5, 6, 5, 0]
[1, 0, 5, 5, 6]
注:本文是在学习牛客算法后自己敲出的,感谢牛客的老师!2020.12.10