diff --git a/budd-common/src/main/java/io/github/ehlxr/algorithm/FindKthLargest.java b/budd-common/src/main/java/io/github/ehlxr/algorithm/FindKthLargest.java new file mode 100644 index 0000000..50be956 --- /dev/null +++ b/budd-common/src/main/java/io/github/ehlxr/algorithm/FindKthLargest.java @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2020 xrv + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package io.github.ehlxr.algorithm; + +/** + * @author ehlxr + * @since 2021-12-28 23:16. + */ +public class FindKthLargest { + public static void main(String[] args) { + int[] nums = new int[]{3, 2, 1, 5, 6, 4}; + System.out.println(findKthLargest(nums, 2)); + } + + public static int findKthLargest2(int[] nums, int k) { + for (int i = nums.length / 2 - 1; i >= 0; i--) { + // 从第一个非叶子结点从下至上,从右至左调整结构 + adjustHeap(nums, i, nums.length); + } + + for (int j = nums.length - 1; j >= 0; j--) { + k--; + + if (k == 0) { + return nums[0]; + } + + swap(nums, 0, j); + adjustHeap(nums, 0, j); + } + + return 0; + } + + public static void adjustHeap(int[] arr, int i, int length) { + // 先取出当前元素 i + int temp = arr[i]; + // 从 i 结点的左子结点开始,也就是 2i+1 处开始 + for (int k = i * 2 + 1; k < length; k = k * 2 + 1) { + // 如果左子结点小于右子结点,k 指向右子结点 + if (k + 1 < length && arr[k] < arr[k + 1]) { + k++; + } + // 如果子节点大于父节点,将子节点和父节点交换 + // if (arr[k] > arr[i]) { + // swap(arr, k, i); + if (arr[k] > temp) { + // 不用进行交换 + arr[i] = arr[k]; + + i = k; + } else { + break; + } + } + + // 将 temp 值放到最终的位置 + arr[i] = temp; + } + + + public static int findKthLargest(int[] nums, int k) { + if (nums == null || nums.length < k) { + return -1; + } + + int q = partition(nums, 0, nums.length - 1); + while (q + 1 != k) { + if (k < q + 1) { + q = partition(nums, 0, q - 1); + } else { + q = partition(nums, q + 1, nums.length - 1); + } + } + + return nums[q]; + } + + + public static int partition(int[] a, int p, int r) { + int pivot = a[r]; + int i = p; + for (int j = p; j < r; j++) { + if (a[j] >= pivot) { + swap(a, i++, j); + } + } + + swap(a, i, r); + return i; + } + + private static void swap(int[] a, int i, int j) { + if (i == j) { + return; + } + int temp = a[i]; + a[i] = a[j]; + a[j] = temp; + } +} diff --git a/budd-common/src/main/java/io/github/ehlxr/algorithm/sort/QuickSort.java b/budd-common/src/main/java/io/github/ehlxr/algorithm/sort/QuickSort.java index cf885c2..ca75aa7 100644 --- a/budd-common/src/main/java/io/github/ehlxr/algorithm/sort/QuickSort.java +++ b/budd-common/src/main/java/io/github/ehlxr/algorithm/sort/QuickSort.java @@ -32,45 +32,57 @@ import java.util.Arrays; */ public class QuickSort { public static void main(String[] args) { - int[] arrs = new int[]{3, 2, 5, 7, 1, 9}; - sort(arrs, 0, arrs.length - 1); + int[] a = new int[]{3, 9, 5, 7, 1, 2}; + sort(a, 0, a.length - 1); - System.out.println(Arrays.toString(args)); + System.out.println(Arrays.toString(a)); } - public static void sort(int[] arrs, int p, int r) { + public static void sort(int[] a, int p, int r) { if (p >= r) { return; } - int k = partition(arrs, p, r); + int q = partition(a, p, r); - sort(arrs, p, k - 1); - sort(arrs, k + 1, r); + sort(a, p, q - 1); + sort(a, q + 1, r); } - public static int partition(int[] arrs, int p, int r) { + /** + * 获取分区点 + *

+ * 图示:https://cdn.jsdelivr.net/gh/0vo/oss/images/quick_sort.jpg + *

+ * 通过游标 i 把 a[p...r] 分成两部分。 + * a[p...i-1] 的元素都是小于 pivot 的,我们暂且叫它 “已处理区间”,a[i...r] 是 “未处理区间”。 + * 我们每次都从未处理的区间 a[i...r] 中取一个元素 a[j],与 pivot 对比, + * 如果小于 pivot,则将其加入到已处理区间的尾部,也就是 a[i] 的位置 + *

+ * 只需要将 a[i] 与 a[j] 交换,就可以在 O(1) 时间复杂度内将 a[j] 放到下标为 i 的位置。 + */ + public static int partition(int[] a, int p, int r) { int i = p; - int pivot = arrs[r]; + int pivot = a[r]; for (int j = p; j < r; j++) { - if (arrs[j] < pivot) { - if (j != i) { - swap(arrs, i, j); - } - i++; + if (a[j] < pivot) { + swap(a, i++, j); } } - swap(arrs, i, r); - System.out.println("i=" + i); + swap(a, i, r); + System.out.println("i=" + i + " " + Arrays.toString(a)); return i; } - public static void swap(int[] arrs, int i, int j) { - int temp = arrs[i]; - arrs[i] = arrs[j]; - arrs[j] = temp; + public static void swap(int[] a, int i, int j) { + if (i == j) { + return; + } + int temp = a[i]; + a[i] = a[j]; + a[j] = temp; }