快速排序

  1. public void quickSort(int nums[],int start,int end){
  2. ....
  3. partition(..);//可以不封装
  4. ....
  5. quickSort(..);
  6. qucikSort(..);
  7. }
  • 一次划分过程是和sentinel的值比较
  • 没有swap, 不止不断交替写值

    快速排序实现一

    快速排序实现二

    快速排序优化-随机化选择哨兵

求第topK大\K小元素 or 求topK大\K小元素子数组

求解top K小元素,和求解top K个小元素(字数组),过程,截止条件是一样的。区别只是return 而已

  • 思路一:全体排序,返回前k个
  • 二:快速排序,单边划分寻找
    • 两种情况的处理巧妙的是一致的
    • 快排中,当你找到pos=k,那么左边的元素全小于num[k] , 尽管还无序,但满足求topK大\K小元素子数组了,没要求结果子数组有序!
    • 代码上,把 target pos 当作全局的位置加以判断,不需要在递归的过程修改target pos . 因为partition函数返回的一次 pos, 也是全局的Index。 比如剑指P206的做法。
  • 三:大根堆

注意:中位数 k = len/2, 实际是滴k+1大的数。可以这么记,topk大还是小,还是中位数,最后转化为目标pos数组的位置来判断。

快速选择代码

  1. public int randomPartition(int[] nums,int start,int end){
  2. //
  3. if(start>=end) return start;
  4. //1.确定sentimal
  5. //要不要做随机化
  6. Random random = new Random();
  7. int exchangePos = start + random.nextInt(end-start+1);
  8. int sentinel = nums[exchangePos];
  9. int tem = nums[start];
  10. nums[start] = nums[exchangePos];
  11. nums[exchangePos] = tem;
  12. //2确定扫描界
  13. int left = start;
  14. int right = end;
  15. //3.开始扫描:注意,不断交替,出来时是 left=right
  16. while(left<right){
  17. while(nums[right]>=sentinel && left<right) right--;
  18. nums[left] = nums[right];
  19. while(nums[left]<= sentinel && left<right) left++;
  20. nums[right] = nums[left];
  21. }
  22. //4.不要忘记放置哨兵
  23. nums[left] = sentinel;
  24. //5.最后返回position
  25. return left;
  26. }

参考代码:

  • 超出数组一半的数,转寻找中位数,随机化快速选择 (但此题有更好的解法,虽然时间复杂度一样) ```java public int majorityElement(int[] nums) {
    1. //解法一 用基于快排的随机快速选择,选择中位数
    2. int k = nums.length/2;
    3. return quickSelectKpos(nums,0,nums.length-1,k);
  1. }
  2. public int quickSelectKpos(int[]nums,int start,int end,int k){
  3. int partiPos = randomPartition(nums,start,end);
  4. if(partiPos == k) return nums[k];
  5. else if(partiPos <k ){
  6. return quickSelectKpos(nums,partiPos+1,end,k);
  7. }else return quickSelectKpos(nums,start,partiPos-1,k);
  8. }
  9. public int randomPartition(int[] nums,int start,int end){
  10. if(start>=end) return start;
  11. Random random = new Random();
  12. int exchangePos = start + random.nextInt(end-start+1);
  13. int sentinel = nums[exchangePos];
  14. int tem = nums[start];
  15. nums[start] = nums[exchangePos];
  16. nums[exchangePos] = tem;
  17. int left = start;
  18. int right = end;
  19. while(left<right){
  20. while(nums[right]>=sentinel && left<right) right--;
  21. nums[left] = nums[right];
  22. while(nums[left]<= sentinel && left<right) left++;
  23. nums[right] = nums[left];
  24. }
  25. //最后这里忘记放置哨兵了
  26. nums[left] = sentinel;
  27. return left;
  28. }

```