From 778402081493315925bec0e906e971a44bc5cd38 Mon Sep 17 00:00:00 2001 From: Leo <582717189@qq.com> Date: Thu, 26 Nov 2020 21:41:53 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=83=E4=B9=A0,=E5=BF=AB=E6=8E=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/leo/class01/BSExist.java | 21 +- src/leo/class01/BSNear.java | 48 ++- src/leo/class01/BubbleSort.java | 14 +- src/leo/class01/EvenTimesOddTimes.java | 27 +- src/leo/class01/KM.java | 40 ++- src/leo/class02/BiggerThanRightTwice.java | 51 ++- src/leo/class02/ReversePair.java | 45 ++- src/leo/class02/SmallSum.java | 43 ++- src/leo/class03/CountOfRangeSum.java | 246 +++++++++++++++ src/leo/class03/QuickSort1.java | 368 ++++++++++++++++++++++ 10 files changed, 890 insertions(+), 13 deletions(-) create mode 100644 src/leo/class03/CountOfRangeSum.java create mode 100644 src/leo/class03/QuickSort1.java diff --git a/src/leo/class01/BSExist.java b/src/leo/class01/BSExist.java index ba4b7cf..ca77c75 100644 --- a/src/leo/class01/BSExist.java +++ b/src/leo/class01/BSExist.java @@ -193,6 +193,25 @@ public class BSExist { return arr[L] == value; } + public static boolean exist9(int[] arr, int value) { + if (arr.length == 0 || arr == null) { + return false; + } + int l = 0; + int r = arr.length - 1; + while (l < r) { + int mid = l + ((r - l) >> 1); + if (arr[mid] > value) { + r = mid - 1; + } else if (arr[mid] < value) { + l = mid + 1; + }else{ + return true; + } + } + return arr[l] == value; + } + /** * 功能描述 : test * @author Leo @@ -221,7 +240,7 @@ public class BSExist { int[] sortArr = ArrayUtil.randomSortArray(maxSize, range); int value = (int) ((range + 1) * Math.random() - (range + 1) * Math.random()); - if (exist8(sortArr, value) != exist(sortArr, value)) { + if (exist9(sortArr, value) != exist(sortArr, value)) { succeed = false; ArrayUtil.printArr(sortArr); break; diff --git a/src/leo/class01/BSNear.java b/src/leo/class01/BSNear.java index 060bb53..f5e1e80 100644 --- a/src/leo/class01/BSNear.java +++ b/src/leo/class01/BSNear.java @@ -231,6 +231,27 @@ public class BSNear { } + public static int BsNearLeft11(int[] arr, int value) { + if (arr.length == 0 || arr == null) { + return -1; + } + int l = 0; + int r = arr.length - 1; + int index = -1; + while (l <= r) { + int mid = l + ((r - l) >> 1); + if (arr[mid] >= value) { + index = mid; + r = mid - 1; + }else{ + l = mid + 1; + } + } + return index; + } + + + /** * 功能描述 : 在有序数组中找出>=某个数最左侧的位置(for test) * @author Leo @@ -433,6 +454,25 @@ public class BSNear { return index; } + public static int BSNearRight9(int[] arr, int value) { + if (arr.length == 0 || arr == null) { + return -1; + } + int l = 0; + int r = arr.length - 1; + int index = -1; + while (l <= r) { + int mid = l + ((r - l) >> 1); + if (arr[mid] <= value) { + index = mid; + l = mid + 1; + }else{ + r = mid - 1; + } + } + return index; + } + public static int forTestBSNearRight(int[] arr, int value) { int index = -1; @@ -456,7 +496,7 @@ public class BSNear { for (int i = 0; i < testTime; i++) { int[] sortArr = randomArray(maxSize, range); int value = (int) ((range + 1) * Math.random() - (range + 1) * Math.random()); - /*int res1 = BSNearLeft10(sortArr, value); + int res1 = BSNearLeft10(sortArr, value); int res2 = forTestBSNearLeft(sortArr, value); if (res1 != res2) { success = false; @@ -464,9 +504,9 @@ public class BSNear { System.out.println("BSNearLeft=" + res1); System.out.println("forTestBSNearLeft=" + res2); break; - }*/ + } - int res3 = BSNearRight8(sortArr, value); + /*int res3 = BSNearRight9(sortArr, value); int res4 = forTestBSNearRight(sortArr, value); if (res3 != res4) { success = false; @@ -474,7 +514,7 @@ public class BSNear { System.out.println("BSNearRight=" + res3); System.out.println("forTestBSNearRight=" + res4); break; - } + }*/ } System.out.println(success ? "Nice!!" : "Fucking Fucked!"); } diff --git a/src/leo/class01/BubbleSort.java b/src/leo/class01/BubbleSort.java index f2cebd7..0d6b20a 100644 --- a/src/leo/class01/BubbleSort.java +++ b/src/leo/class01/BubbleSort.java @@ -168,6 +168,18 @@ public class BubbleSort { } + public static void bubbleSort12(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + for (int i = arr.length - 1; i >= 0; i--) { + for (int j = 0; j < i; j++) { + if (arr[j] > arr[i]) { + swap(arr, j, i); + } + } + } + } /** @@ -200,7 +212,7 @@ public class BubbleSort { for (int i = 0; i < testOfTime; i++) { int[] arr = ArrayUtil.randomArray(maxSize, range); int[] anotherArr = ArrayUtil.copyArray(arr); - bubbleSort11(arr); + bubbleSort12(arr); Arrays.sort(anotherArr); if (!ArrayUtil.isEqual(arr, anotherArr)) { succeed = false; diff --git a/src/leo/class01/EvenTimesOddTimes.java b/src/leo/class01/EvenTimesOddTimes.java index 90f1176..39b1df4 100644 --- a/src/leo/class01/EvenTimesOddTimes.java +++ b/src/leo/class01/EvenTimesOddTimes.java @@ -79,6 +79,14 @@ public class EvenTimesOddTimes { System.out.println(eor); } + public static void printOdd7(int[] arr) { + int eor = 0; + for (int num : arr) { + eor ^= num; + } + System.out.println(eor); + } + /** * 功能描述 : 有两种数出现了奇数次,找出他 @@ -206,12 +214,27 @@ public class EvenTimesOddTimes { System.out.println(eorOther+" "+(eor^eorOther)); } + public static void printOddTwo8(int[] arr) { + int eor = 0; + for (int num : arr) { + eor ^= num; + } + int rightOne = eor & (-eor); + int anotherEor = 0; + for (int num : arr) { + if ((rightOne & num) != 0) { + anotherEor ^= num; + } + } + System.out.println(anotherEor + " " + (eor ^ anotherEor)); + } + public static void main(String[] args){ int[] arrOne = {1, 1, 5, 5, 8, 1, 8, 5, 5}; - printOdd6(arrOne); + printOdd7(arrOne); int[] arrTwo = {1, 1, 9, 5, 5, 8, 1, 8, 9, 5, 5, 5}; - printOddTwo7(arrTwo); + printOddTwo8(arrTwo); } diff --git a/src/leo/class01/KM.java b/src/leo/class01/KM.java index 363765f..72a83be 100644 --- a/src/leo/class01/KM.java +++ b/src/leo/class01/KM.java @@ -153,6 +153,44 @@ public class KM { return ans; } + public static int onlyKTime6(int[] arr,int k,int m){ + int[] t = new int[32]; + for (int num : arr) { + for (int i = 0; i < t.length; i++) { + t[i] += (num >> i) & 1; + } + } + int ans = 0; + for (int i = 0; i < t.length; i++) { + if (t[i] % m != 0) { + if (t[i] % m == k) { + ans |= (1 << i); + }else{ + return -1; + } + } + } + + if (ans == 0) { + int count = 0; + for (int num : arr) { + if (num == 0) { + count++; + } + } + if (count == k) { + return ans; + } else { + return -1; + } + } + + + return ans; + + } + + public static void main(String[] args) { int maxKinds = 20; int range = 50; @@ -169,7 +207,7 @@ public class KM { } int[] arr = randomArray(maxKinds, range, k, m); - int ans = onlyKTime5(arr, k, m); + int ans = onlyKTime6(arr, k, m); int ans2 = testForOnlyKTimes(arr, k, m); if (ans != ans2) { System.out.println(ans); diff --git a/src/leo/class02/BiggerThanRightTwice.java b/src/leo/class02/BiggerThanRightTwice.java index b4dc78a..dc9e4c2 100644 --- a/src/leo/class02/BiggerThanRightTwice.java +++ b/src/leo/class02/BiggerThanRightTwice.java @@ -126,7 +126,7 @@ class BiggerThanRightTwice2 { int windowR = m + 1; int res = 0; for (int i = l; i <= m; i++) { - while (windowR <= r && arr[i] > (arr[windowR]) << 1) { + while (windowR <= r && arr[i] > (arr[windowR] << 1)) { windowR++; } res += windowR - m - 1; @@ -154,6 +154,53 @@ class BiggerThanRightTwice2 { } +class BiggerThanRightTwice3 { + + public static int biggerTwice(int[] arr) { + if (arr.length < 2 || arr == null) { + return 0; + } + return process(arr, 0, arr.length - 1); + } + + private static int process(int[] arr, int l, int r) { + if (l == r) { + return 0; + } + int m = l + ((r - l) >> 1); + return process(arr, l, m) + process(arr, m + 1, r) + merge(arr, l, m, r); + } + + private static int merge(int[] arr, int l, int m, int r) { + int res = 0; + int windowR = m + 1; + for (int i = l; i <= m; i++) { + while (windowR <= r && arr[i] > (arr[windowR] << 1)) { + windowR++; + } + res += windowR - m-1; + } + + int p1 = l; + int p2 = m + 1; + int i = 0; + int[] help = new int[r - l + 1]; + while (p1 <= m && p2 <= r) { + help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; + } + while (p1 <= m) { + help[i++] = arr[p1++]; + } + while (p2 <= r) { + help[i++] = arr[p2++]; + } + for (i = 0; i < help.length; i++) { + arr[l + i] = help[i]; + } + return res; + } +} + class TestBiggerThanRightTwice { public static int biggerTwice(int[] arr) { @@ -179,7 +226,7 @@ class Main{ for (int i = 0; i < testTime; i++) { int[] arr = generateRandomArray(sizeMax, range); int[] copyArray = copyArray(arr); - int res = BiggerThanRightTwice2.biggerTwice(arr); + int res = BiggerThanRightTwice3.biggerTwice(arr); int res1 = TestBiggerThanRightTwice.biggerTwice(copyArray); if (res != res1) { System.out.println("res : " + res + " " + " res1: " + res1); diff --git a/src/leo/class02/ReversePair.java b/src/leo/class02/ReversePair.java index 0acc74e..49d3d6d 100644 --- a/src/leo/class02/ReversePair.java +++ b/src/leo/class02/ReversePair.java @@ -8,6 +8,8 @@ import leo.util.ArrayUtil; * @DATE 2020/11/23 9:48 下午 * @Description 在一段数组中 返回有多少逆序对 * 合并的时候 两侧下标-- + * 任何一个前面的数a,和任何一个后面的数b, + * 如果(a,b)是降序的 */ public class ReversePair { @@ -178,6 +180,47 @@ class ReversePair3 { } } +class ReversePair4{ + public static int reversePairNumber(int[] arr) { + if (arr.length < 2 || arr == null) { + return 0; + } + return process(arr, 0, arr.length - 1); + } + + private static int process(int[] arr, int l, int r) { + + if (l == r) { + return 0; + } + int m = l + ((r - l) >> 1); + return process(arr, l, m) + process(arr, m + 1, r) + merge(arr, l, m, r); + } + + private static int merge(int[] arr, int l, int m, int r) { + int p1 = m; + int p2 = r; + int[] help = new int[r - l + 1]; + int i = help.length - 1; + int res = 0; + while (p1 >= l && p2 > m) { + res += arr[p1] > arr[p2] ? p2 - m : 0; + help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--]; + } + while (p1 >= l) { + help[i--] = arr[p1--]; + } + while(p2>m){ + help[i--] = arr[p2--]; + } + for (i = 0; i < help.length; i++) { + arr[l + i] = help[i]; + } + return res; + + } +} + class TestReversePair{ public static int reversePairNumber(int[] arr) { int res = 0; @@ -216,7 +259,7 @@ class TestReversePair{ for (int i = 0; i < testTime; i++) { int[] arr = randomArray(sizeMax, range); int[] copyArr = copyArray(arr); - int num = ReversePair3.reversePairNumber(arr); + int num = ReversePair4.reversePairNumber(arr); int copyNum = reversePairNumber(copyArr); if (num != copyNum) { System.out.println("num : "+num); diff --git a/src/leo/class02/SmallSum.java b/src/leo/class02/SmallSum.java index bcbb043..a8e0c40 100644 --- a/src/leo/class02/SmallSum.java +++ b/src/leo/class02/SmallSum.java @@ -231,6 +231,47 @@ class SmallSum4{ } } + +class SmallSum5{ + + public static int smallSum(int[] arr) { + if (arr.length < 2 || arr == null) { + return 0; + } + return process(arr, 0, arr.length - 1); + } + + private static int process(int[] arr, int l, int r) { + if (l == r) { + return 0; + } + int m = l + ((r - l) >> 1); + return process(arr, l, m) + process(arr, m + 1, r) + merge(arr, l, m, r); + } + + private static int merge(int[] arr, int l, int m, int r) { + int res = 0; + int p1 = l; + int p2 = m + 1; + int i = 0; + int[] help = new int[r - l + 1]; + while (p1 <= m && p2 <= r) { + res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; + help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; + } + while (p1 <= m) { + help[i++] = arr[p1++]; + } + while (p2 <= r) { + help[i++] = arr[p2++]; + } + for (i = 0; i < help.length; i++) { + arr[l + i] = help[i]; + } + return res; + } +} + class TestSmallSum{ public static int smallSum(int[] arr) { if (arr.length < 2 || arr == null) { @@ -274,7 +315,7 @@ class TestMain { for (int i = 0; i < testTime; i++) { int[] arr = ArrayUtil.randomArray(maxSize, range); int[] copyArray = ArrayUtil.copyArray(arr); - int sum = SmallSum4.smallSum(arr); + int sum = SmallSum5.smallSum(arr); int testSum = TestSmallSum.smallSum(copyArray); if (testSum != sum) { System.out.println("sum :" + sum + ", testSum : " + testSum); diff --git a/src/leo/class03/CountOfRangeSum.java b/src/leo/class03/CountOfRangeSum.java new file mode 100644 index 0000000..a75afec --- /dev/null +++ b/src/leo/class03/CountOfRangeSum.java @@ -0,0 +1,246 @@ +package leo.class03; + +import leo.util.ArrayUtil; + +/** + * @author Leo + * @ClassName CountOfRangeSum + * @DATE 2020/11/25 2:54 下午 + * @Description + * 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper。 + * 假设0-i整体累加和是x,求必须以i位置结尾的子数组,目标有多少个在[lower,upper]范围上 + * 等同于求在i之前的所有累加和中有多少个累加和在[x-upper,x-lower]上. + * https://leetcode-cn.com/problems/count-of-range-sum/ + */ +class CountOfRangeSum { + + public static int countRangeSum(int[] nums, int lower, int upper) { + if (nums.length == 0 || nums == null) { + return 0; + } + long[] sum = new long[nums.length]; + sum[0] = nums[0]; + for (int i = 1; i < nums.length; i++) { + sum[i] = sum[i - 1] + nums[i]; + } + return process(sum, 0, nums.length - 1, lower, upper); + } + + private static int process(long[] sum, int l, int r, int lower, int upper) { + if (l == r) { + return sum[l] >= lower && sum[l] <= upper ? 1 : 0; + } + int m = l + ((r - l) >> 1); + return process(sum, l, m, lower, upper) + process(sum, m + 1, r, lower, upper) + merge(sum, l, m, r, lower, upper); + } + + private static int merge(long[] arr, int l, int m, int r, int lower, int upper) { + int res = 0; + int windowL = l; + int windowR = l; + //左右指针开始对比 + for (int i = m + 1; i <= r; i++) { + long max = arr[i] - lower; + long min = arr[i] - upper; + //如果左侧的数小于等于右侧数减lower 代表在lower范围,指针前进 + while (windowR <= m && arr[windowR] <= max) { + windowR++; + } + //如果左侧的数小于右侧书减upper,代表在upper范围之内 + //条件不是小于等于的原因是不知道有左侧的数有几个等于upper 等于也在upper范围内 + while (windowL <= m && arr[windowL] < min) { + windowL++; + } + //左侧的两个指针相减,得到一共有个数lower和upper范围内 + res += windowR - windowL; + } + int p1 = l; + int p2 = m + 1; + long[] help = new long[r - l + 1]; + int i = 0; + while (p1 <= m && p2 <= r) { + help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; + } + while (p1 <= m) { + help[i++] = arr[p1++]; + } + while(p2<=r) { + help[i++] = arr[p2++]; + } + for (i = 0; i < help.length; i++) { + arr[l + i] = help[i]; + } + return res; + } + +} + +class CountOfRangeSum1 { + public static int countRangeSum(int[] nums, int lower, int upper) { + if (nums == null || nums.length == 0) { + return 0; + } + long[] sum = new long[nums.length]; + sum[0] = nums[0]; + for (int i = 1; i < nums.length; i++) { + sum[i] = sum[i - 1] + nums[i]; + } + return process(sum, 0, nums.length - 1, lower, upper); + } + + private static int process(long[] sum, int l, int r,int lower,int upper) { + + + if (l == r) { + return sum[l] >= lower && sum[r] <= upper ? 1 : 0; + } + + int m = l + ((r - l) >> 1); + return process(sum, l, m, lower, upper) + process(sum, m + 1, r, lower, upper) + merge(sum, l, m, r, lower, upper); + + } + + private static int merge(long[] sum, int l, int m, int r, int lower, int upper) { + + int windowR = l; + int windowL = l; + int res = 0; + for (int i = m + 1; i <= r; i++) { + + long min = sum[i] - upper; + long max = sum[i] - lower; + while (windowR <= m && sum[windowR] <= max) { + windowR++; + } + while (windowL <= m && sum[windowL] < min) { + windowL++; + } + res += windowR - windowL; + } + int p1 = l; + int p2 = m + 1; + long[] help = new long[r - l + 1]; + int i = 0; + while (p1 <= m && p2 <= r) { + help[i++] = sum[p1] <= sum[p2] ? sum[p1++] : sum[p2++]; + } + while (p1 <= m) { + help[i++] = sum[p1++]; + } + while(p2 <= r) { + help[i++] = sum[p2++]; + } + for (i = 0; i < help.length; i++) { + sum[l + i] = help[i]; + } + return res; + } + +} + + +class CountOfRangeSum2 { + + public static int countRangeSum(int[] nums, int lower, int upper) { + if (nums == null || nums.length == 0) { + return 0; + } + long[] sum = new long[nums.length]; + sum[0] = nums[0]; + for (int i = 1; i < nums.length; i++) { + sum[i] = sum[i - 1] + nums[i]; + } + return process(sum, 0, sum.length - 1, lower, upper); + + } + + private static int process(long[] sum, int l, int r, int lower, int upper) { + if (l == r) { + return sum[l] >= lower & sum[l] <= upper ? 1 : 0; + } + int m = l + ((r - l) >> 1); + return process(sum,l,m,lower,upper)+process(sum,m+1,r,lower,upper)+merge(sum,l,m,r,lower,upper); + } + + private static int merge(long[] sum, int l, int m, int r, int lower, int upper) { + int windowL = l; + int windowR = l; + int res = 0; + for (int i = m + 1; i <= r; i++) { + long max = sum[i] - lower; + long min = sum[i] - upper; + while (windowR <= m && sum[windowR] <= max) { + windowR++; + } + while (windowL <= m && sum[windowL] < min) { + windowL++; + } + res += windowR - windowL; + } + int p1 = l; + int p2 = m + 1; + long[] help = new long[r - l + 1]; + int i = 0; + while (p1 <= m && p2 <= r) { + help[i++] = sum[p1] <= sum[p2] ? sum[p1++] : sum[p2++]; + } + while (p1 <= m) { + help[i++] = sum[p1++]; + } + while (p2 <= r) { + help[i++] = sum[p2++]; + } + for (i = 0; i < help.length; i++) { + sum[l + i] = help[i]; + } + return res; + } +} + +class MainTest{ + + public static int countRangeSum(int[] nums, int lower, int upper) { + int count = 0; + for(int i=0;i=lower && sum<=upper) count++; + } + } + return count; + } + + + public static void main(String[] args) { + int testTime = 1000; + int sizeMax = 80; + int range = 50; + System.out.println("start!"); + + for (int i = 0; i < testTime; i++) { + int[] arr = ArrayUtil.randomArray(sizeMax, range); + int[] copyArray = ArrayUtil.copyArray(arr); + int lower = (int) ((range * Math.random() + 1)-(range * Math.random() + 1)); + int upper; + do { + upper = (int) ((range * Math.random() + 1) - (range * Math.random() + 1)); + } while (upper <= lower); + int sumCount = CountOfRangeSum2.countRangeSum(arr, lower, upper); + int testSumCount = countRangeSum(copyArray, lower, upper); + if (sumCount != testSumCount) { + System.out.println("sumCount :" + sumCount+" testSumCount : "+testSumCount); + System.out.println("fuck!"); + break; + } + + } + System.out.println("end!"); + + } + + + +} + + diff --git a/src/leo/class03/QuickSort1.java b/src/leo/class03/QuickSort1.java new file mode 100644 index 0000000..65320fb --- /dev/null +++ b/src/leo/class03/QuickSort1.java @@ -0,0 +1,368 @@ +package leo.class03; + +import com.sun.org.apache.bcel.internal.generic.POP2; +import com.sun.xml.internal.bind.v2.model.core.ID; +import leo.util.ArrayUtil; + +import java.util.Arrays; +import java.util.Stack; + +/** + * @author Leo + * @ClassName QuickSort1 + * @DATE 2020/11/26 11:17 上午 + * @Description 快排1.0 + * O(N²) 最差情况 + * 范围内最后一个数为比较值x,[<=x>],x一定在左侧的最后一个位置,返回比较值得下标 + * 只记录右侧最小位置下标,如果index的值小于或等于右侧最后位置的数, + * index与最小位置的数后一位交换,最小位置下标更新 + * + * T(N) = a * T(N/b) + O(N^d)(其中的a、b、d都是常数) + * 的递归函数,可以直接通过Master公式来确定时间复杂度 + * 如果 log(b,a) < d,复杂度为O(N^d) + * 如果 log(b,a) > d,复杂度为O(N^log(b,a)) + * 如果 log(b,a) == d,复杂度为O(N^d * logN) + * + */ +class QuickSort1 { + public static void quickSort(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + process(arr, 0, arr.length - 1); + } + + private static void process(int[] arr, int l, int r) { + if (l >= r) { + return; + } + int m = partition(arr, l, r); + process(arr, l, m-1); + process(arr, m + 1, r); + } + + private static int partition(int[] arr, int l, int r) { + if (l > r) { + return -1; + } + if (l == r) { + return l; + } + int less = l-1; + int index = l; + while (index < r) { + if (arr[index] <= arr[r]) { + swap(arr, index, ++less); + } + index++; + } + swap(arr, r, ++less); + return less; + } + + private static void swap(int[] arr, int i, int j) { + if (i == j || arr[i] == arr[j]) { + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } + +} + + +/** + * @author Leo + * @ClassName QuickSort1 + * @DATE 2020/11/26 11:17 上午 + * @Description 快排2.0 + * O(N²) 最差情况 + * 中间位置固定,左右两边有序 + * + */ +class QuickSort2 { + + public static void quickSort(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + process(arr, 0, arr.length - 1); + } + + public static void process(int[] arr, int l, int r) { + if (l >= r) { + return; + } + int[] equalsArea = partition(arr, l, r); + process(arr, l, equalsArea[0] - 1); + process(arr, equalsArea[1] + 1, r); + } + + //netherlandsFlag + //荷兰国旗问题 + private static int[] partition(int[] arr, int l, int r) { + if (l > r) { + return new int[]{-1, -1}; + } + if (l == r) { + return new int[]{l, r}; + } + + int leftIndex = l - 1; + int rightIndex = r; + int index = l; + while (index < rightIndex) { + if (arr[index] < arr[r]) { + swap(arr, index++, ++leftIndex); + } else if (arr[index] > arr[r]) { + swap(arr, index, --rightIndex); + }else{ + index++; + } + } + swap(arr, r, rightIndex); + return new int[]{leftIndex+1, rightIndex}; + } + + + private static void swap(int[] arr, int i, int j) { + if (i == j || arr[i] == arr[j]) { + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } +} + + +/** + * @author Leo + * @ClassName QuickSort1 + * @DATE 2020/11/26 11:17 上午 + * @Description 快排3.0 + * O(N*logN) + * 额外空间复杂度o(n) + * + */ +class QuickSort3 { + + public static void quickSort(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + process(arr, 0, arr.length - 1); + } + + public static void process(int[] arr, int l, int r) { + if (l >= r) { + return; + } + swap(arr, (int) (l + (Math.random() * (r - l + 1))), r); + int[] equalArea = partition(arr, l, r); + process(arr, l, equalArea[0] - 1); + process(arr, equalArea[1] + 1, r); + } + + public static int[] partition(int[] arr, int l, int r) { + if (l > r) { + return new int[]{-1, -1}; + } + if (l == r) { + return new int[]{l, r}; + } + int leftIndex = l - 1; + int rightIndex = r; + int index = l; + while (index < rightIndex) { + if (arr[index] == arr[r]) { + index++; + } else if (arr[index] < arr[r]) { + swap(arr, index++, ++leftIndex); + } else if (arr[index] > arr[r]) { + swap(arr, index, --rightIndex); + } + } + swap(arr, r, rightIndex); + + return new int[]{leftIndex + 1, rightIndex}; + } + + public static void swap(int[] arr, int i, int j) { + if (arr[i] == arr[j] || i == j) { + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } +} + + +class QuickSort3_1{ + + public static void quickSort(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + + process(arr, 0, arr.length - 1); + } + + private static void process(int[] arr, int l, int r) { + + if (l >= r) { + return; + } + + swap(arr, (int) (l + ((r - l + 1) * Math.random())), r); + int[] equalArea = partition(arr, l, r); + process(arr, l, equalArea[0] - 1); + process(arr, equalArea[1] + 1, r); + + } + + private static int[] partition(int[] arr, int l, int r) { + if (l > r) { + return new int[]{-1, -1}; + } + if (l == r) { + return new int[]{l, r}; + } + int leftIndex = l - 1; + int rightIndex = r; + int index = l; + while (index < rightIndex) { + if (arr[index] == arr[r]) { + index++; + } else if (arr[index] > arr[r]) { + swap(arr, index, --rightIndex); + } else if (arr[index] < arr[r]) { + swap(arr, index++, ++leftIndex); + } + } + swap(arr, r, rightIndex); + return new int[]{leftIndex + 1, rightIndex}; + + } + + + public static void swap(int[] arr, int i, int j) { + if (arr[i] == arr[j] || i == j) { + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + + } + + +} + + + +class QuickSortUnRecursive{ + + private static class Op { + public int l; + public int r; + + public Op(int l, int r) { + this.l = l; + this.r = r; + } + } + + public static void quickSort(int[] arr) { + if (arr.length < 2 || arr == null) { + return; + } + swap(arr, arr.length - 1, (int) (arr.length * Math.random())); + int[] equalArea = partition(arr, 0, arr.length - 1); + Stack stack = new Stack<>(); + int l = equalArea[0] - 1; + int r = equalArea[1] + 1; + stack.push(new Op(0, l)); + stack.push(new Op(r, arr.length - 1)); + while (!stack.isEmpty()) { + Op pop = stack.pop(); + int pl = pop.l; + int pr = pop.r; + if (pl < pr) { + swap(arr, (int) (pl + (Math.random() * (pr - pl + 1))), pr); + equalArea = partition(arr, pl, pr); + l = equalArea[0] - 1; + r = equalArea[1] + 1; + stack.push(new Op(pl, l)); + stack.push(new Op(r, pr)); + } + } + + } + + + + public static int[] partition(int[] arr, int l, int r) { + if (l > r) { + return new int[]{-1, -1}; + } + if (l==r){ + return new int[]{l, r}; + } + int leftIndex = l - 1; + int rightIndex = r; + int index = l; + while (index < rightIndex) { + if (arr[index] == arr[r]) { + index++; + } else if (arr[index] < arr[r]) { + swap(arr, index++, ++leftIndex); + } else if (arr[index] > arr[r]) { + swap(arr, index, --rightIndex); + } + } + swap(arr, r, rightIndex); + return new int[]{leftIndex + 1, rightIndex}; + } + + private static void swap(int[] arr, int i, int j) { + if (i == j || arr[i] == arr[j]) { + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; + arr[i] = arr[i] ^ arr[j]; + } + + +} + + +class TestMain { + + + public static void main(String[] args){ + int testTimes = 1000; + int sizeMax = 50; + int range = 50; + System.out.println("start"); + + for (int i = 0; i < testTimes; i++) { + int[] arr = ArrayUtil.randomArray(sizeMax, range); + int[] copyArray = ArrayUtil.copyArray(arr); + QuickSort3_1.quickSort(arr); + Arrays.sort(copyArray); + if (!ArrayUtil.isEqual(arr, copyArray)) { + ArrayUtil.printArr(arr); + ArrayUtil.printArr(copyArray); + System.out.println("fuck"); + break; + } + } + System.out.println("end"); + + } + +}