8.10 第一次写无法 AC
8.11 可以 AC


第一次复习
9.7 可以 AC
9.14 无法 AC 差一点
9.15 可以 AC

题目描述


原题链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/

解题思路:快速选择


官方题解的文字说明挺好的,可以去看看:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/

快速选择和快速排序一样,都是要写个方法,然后该方法再调用切分方法!

8.10 心得:

  • 最大的第 K 个元素 = 从小到大排序的倒数第 K 个元素 = 数组下标为 nums.length - k


  • 看官方题解文字说明得出得心得:

    • 快速排序是切分后的左右两区间都得递归的去排序,而快速选择不用切分后都去递归左右两区间,只需判断我们需要找的数据下标在哪个区间然后去递归那一边的区间就行了。
    • 并且也不用递归到全部元素有序,只需要得到我们想要的元素的下标位置确定了即可,该位置的元素就是我们想要的,此时的状态是该元素左侧的元素都比它小但不是元素的,右侧的元素都比它大并且也不是有序的,左右两侧都不是有序的也没关系,我们不用继续递归的去排成有序的,只需要返回我们需要的下标的元素即可,可以肯定该元素在原数组中一定是有序的!
  • 所以,快排的时间复杂度是 O(Nlogn) 而快速选择的时间复杂度是 O(N),为啥是 O(N) 原因在上面。

9.14 心得:

  • 下面第 7 行代码和快排不同,就随便瞎试,对了就行

    1. class Solution {
    2. public int findKthLargest(int[] nums, int k) {
    3. return quickSelect(nums, 0, nums.length - 1, nums.length - k);
    4. }
    5. public int quickSelect(int[] nums, int l, int r, int k) {
    6. if(l > r) return 0;
    7. int OkSortIndex = partition(nums, l, r);
    8. if(k == OkSortIndex) return nums[OkSortIndex];
    9. else if(k < OkSortIndex) return quickSelect(nums, l, OkSortIndex - 1, k);
    10. else return quickSelect(nums, OkSortIndex + 1, r, k);
    11. }
    12. public int partition(int[] nums, int l, int r) {
    13. // 比如:new Random().nextInt(100) 的取值范围是 [0, 100)
    14. swap(nums, l, new Random().nextInt(r - l + 1) + l); // 随机化,防止最坏情况
    15. int cut = nums[l];
    16. int i = l, j = r;
    17. while(i < j) {
    18. while(i < j && nums[j] >= cut) j--;
    19. while(i < j && nums[i] <= cut) i++;
    20. if(i < j) swap(nums, i, j);
    21. }
    22. swap(nums, l, j);
    23. return j;
    24. }
    25. public void swap(int[] nums, int i, int j) {
    26. int tmp = nums[i];
    27. nums[i] = nums[j];
    28. nums[j] = tmp;
    29. }
    30. }