package com.example.demo.algorithm.D004;
/**
* @Description :
* 题目:
* 给定一个数组arr,和一个整数num。请把小于num的数放在数组左边,等于num的数放在中间,大于num的数放在数组的右边。
* 要求时间复杂度O(N),额外空间复杂度(1)
*
* partition流程:
* 1)将整个数组左边划分为小于区域,下标初始值为-1,右边花费为大于区域,下标初始值为r+1
* 2)当i位置的数小于num时,当前数arr[i]与小于区域下一个数交换,小于区右扩,i++
* 3) 当i位置的数大于num时,当前数arr[i]与大于区域上一个数交换,大于区左扩,i原地不变(因为此时i位置的数没有看过)
* 4)当i位置的数等于num时,i++
*
* [5,3,7,2,3,4,1] i=0 a=-1 b=7 num=3(a:左边界 b:右边界)
* 0 1 2 3 4 5 6
* 5 > 3 arr[0] swap arr[6] i=0 a=-1 b=6
*
* [1,3,7,2,3,4,5]
* 0 1 2 3 4 5 6
* 1 < 3 arr[0] swap arr[0] i=1 a=0 b=6
*
* [1,3,7,2,3,4,5]
* 0 1 2 3 4 5 6
* 3 = 3 i=2 a=0 b=6
*
* [1,3,7,2,3,4,5]
* 0 1 2 3 4 5 6
* 7 > 3 arr[2] swap arr[5] i=2, a=0, b=5
*
* [1,3,4,2,3,7,5]
* 0 1 2 3 4 5 6
* 4 > 3 arr[2] swap arr[4] i=2 a=0 b=4
*
* [1,3,3,2,4,7,5]
* 0 1 2 3 4 5 6
* 3 == 3 i=3 a=0 b=4
*
* [1,3,3,2,4,7,5]
* 0 1 2 3 4 5 6
* 2 < 3 arr[3] swap arr[1] i=4 a=1 b=4
*
* [1,2,3,3,4,7,5]
* 0 1 2 3 4 5 6
* a b
* 小于3的在左边,等于3的在中间,大于3的在右边
*
* @Author : Darren
* @Date : 2021 年 02 月 25 日 20:31:54
* @since : 1.0
*/
public class J002_Partition {
public static void main(String[] args) {
int[] arr = {5,3,7,2,3,4,1};
int[] partition = partition(arr, 0, arr.length - 1, 3);
printArray(arr);
printArray(partition);
}
/**
* 给定一个数partition
* @param arr
* @param l
* @param r
* @param num
* @return
*/
public static int[] partition(int[] arr, int l, int r, int num){
if (l > r){
return new int[]{-1,-1};
}
if (l == r){
return new int[]{l,r};
}
//左边界
int lessEqual = l-1;
//右边界
int moreEqual = r+1;
int index = l;
while (index < moreEqual){
// 当i位置的数小于num时,当前数arr[i]与小于区域下一个数交换,小于区右扩,i++
// 当i位置的数大于num时,当前数arr[i]与大于区域上一个数交换,大于区左扩,i不变
// 当i位置的数等于num时,i++
if (arr[index] < num){
swap(arr, index++, ++lessEqual);
}else if(arr[index] > num){
swap(arr, index, --moreEqual);
}else{
index++;
}
}
return new int[]{lessEqual,moreEqual};
}
private static void swap(int[] arr, int i, int j) {
/*arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];*/
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* 生成一个随机数组
* @param maxSize
* @param maxValue
* @return
*/
public static int[] generateRandomArray(int maxSize, int maxValue){
//Math.random() [0,1)
//Math.random() * N [0,N)
//(int)(Math.random() * N) [0,N-1]
int[] arrays = new int[(int) ((maxSize+1) * Math.random())];
for (int i = 0; i < arrays.length; i++) {
arrays[i] = (int) ((maxValue+1) * Math.random()) - (int)(maxValue * Math.random());
}
return arrays;
}
/**
* 打印数组
* @param arrays
*/
public static void printArray(int[] arrays){
if (arrays == null){
return;
}
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
System.out.println();
}
/**
* 复制数组
*/
public static int[] copyArray(int[] arr){
if (arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
/**
* 判断两个数组是否相等
* @param arr1
* @param arr2
* @return
*/
public static boolean isArrayEqual(int[] arr1, int[] arr2){
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)){
return false;
}
if (arr1 == null && arr2 == null){
return true;
}
if (arr1.length != arr2.length){
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]){
return false;
}
}
return true;
}
}
【知识积累】荷兰国旗问题2:给定一个数组arr,和一个整数num。请把小于num的数放在数组左边,等于num的数放在中间,大于num的数放在数组的右边。要求时间复杂度O(N),额外空间复杂度(1)
于 2022-05-29 15:21:14 首次发布