随机快排

  1. import java.util.Random;
  2. public class QuickSort {
  3. private int[] arr;
  4. public QuickSort(int[] a) {
  5. this.arr = a.clone();
  6. }
  7. public void sort() {
  8. _sort(0, arr.length - 1);
  9. }
  10. private void _sort(int left, int right) {
  11. if (left >= right) {
  12. return;
  13. }
  14. int mid = partition(left, right);
  15. _sort(left, mid - 1);
  16. _sort(mid + 1, right);
  17. }
  18. /**
  19. * 随机找出一个数mid作为中间值
  20. * 将arr中下标范围[left, right]内的元素分为两部分
  21. * 左侧均比不大于mid, 右侧均不小于mid
  22. *
  23. * @param left 起始下标
  24. * @param right 终止下标
  25. * @return 中间值mid的下标
  26. */
  27. private int partition(int left, int right) {
  28. int index = new Random().nextInt(right - left + 1) + left;
  29. int temp = arr[index];
  30. arr[index] = arr[left];
  31. arr[left] = temp;
  32. int mid = arr[left];
  33. while (left < right) {
  34. while ((left < right) && (arr[right] >= mid)) {
  35. --right;
  36. }
  37. arr[left] = arr[right];
  38. while ((left < right) && (arr[left] <= mid)) {
  39. ++left;
  40. }
  41. arr[right] = arr[left];
  42. }
  43. arr[left] = mid;
  44. return left;
  45. }
  46. public void print() {
  47. for (int i : arr) {
  48. System.out.print(i + " ");
  49. }
  50. System.out.println();
  51. }
  52. public static void main(String[] args) {
  53. QuickSort q = new QuickSort(new int[]{56, 645, 43, 343, 55, 546, 43, 65, 6, 43, 5, 64, 4, 35, 6});
  54. q.sort();
  55. q.print();
  56. }
  57. }

第k小的数

  1. import java.util.*;
  2. public class Finder {
  3. private final int SCOPE = 128;
  4. public int findKth(int[] a, int n, int K) {
  5. return maxK(a, 0, n - 1, K);
  6. }
  7. /**
  8. * 在数组arr下标范围[left, right]之间找到第k大的数
  9. *
  10. * @param arr 数组
  11. * @param left 起始下标
  12. * @param right 终止下标
  13. * @param k 索引值, 从1开始
  14. * @return
  15. */
  16. private int maxK(int[] arr, int left, int right, int k) {
  17. if (left > right) {
  18. return -1;
  19. }
  20. // 小范围可以不再分治, 直接排序
  21. if (right - left + 1 <= SCOPE) {
  22. Arrays.sort(arr, left, right + 1);
  23. return arr[left + k - 1];
  24. }
  25. int mid = partition(arr, left, right);
  26. int index = mid - left + 1;
  27. if (index > k) {
  28. return maxK(arr, left, mid - 1, k);
  29. } else if (index < k) {
  30. return maxK(arr, mid + 1, right, k - index);
  31. }
  32. return arr[mid];
  33. }
  34. /**
  35. * 随机找出一个数mid作为中间值
  36. * 将arr中下标范围[left, right]内的元素分为两部分
  37. * 左侧均比不大于mid, 右侧均不小于mid
  38. *
  39. * @param arr 数组
  40. * @param left 起始下标
  41. * @param right 终止下标
  42. * @return 中间值mid的下标
  43. */
  44. private int partition(int[] arr, int left, int right) {
  45. int index = new Random().nextInt(right - left + 1) + left;
  46. int temp = arr[index];
  47. arr[index] = arr[left];
  48. arr[left] = temp;
  49. int mid = arr[left];
  50. while (left < right) {
  51. while ((left < right) && (arr[right] <= mid)) {
  52. --right;
  53. }
  54. arr[left] = arr[right];
  55. while ((left < right) && (arr[left] >= mid)) {
  56. ++left;
  57. }
  58. arr[right] = arr[left];
  59. }
  60. arr[left] = mid;
  61. return left;
  62. }
  63. public static void main(String[] args) {
  64. Finder finder = new Finder();
  65. System.out.println(finder.findKth(new int[]{3, 4, 5, 6, 2, 1, 7, 8, 9}, 9, 2));
  66. }
  67. }

相关题目