# 快速排序解决 top K问题

  1. 数组中的第K个最大元素
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;


class Solution {
    public int findKthLargest(int[] nums, int k) {
         
        return SortUtil.quickSelect(nums,0,nums.length-1,nums.length-k);
    }


    static class SortUtil {
        static void quickSort(int[] p, int i, int j) {
            if (j <= i) return;
            int pivotIndex = ThreadLocalRandom.current().nextInt(i, j + 1);
            int pivot = p[pivotIndex];
            swap(p, i, pivotIndex);
            int p1 = i, p2 = j;
            while (p1 < p2) {


                while (p1 < p2 && p[p2] >= pivot) {
                    p2--;
                }
                while (p1 < p2 && p[p1] <= pivot) {
                    //p1 跑太过了,导致  p1>=p2 但是, p[p2] >= pivot ,所以,排序不正确,因此,必须要保证 p[p2] >= pivot ,p2跑到最左边
                    p1++;
                }


                if (p1 < p2) {

                    swap(p, p1, p2);
                }
                // System.out.println(Arrays.toString(p)+ " :"+p1+" "+p2);

            }
            swap(p, i, p1);
            quickSort(p, i, p1 - 1);
            quickSort(p, p1 + 1, j);

        }

        static void swap(int[] p, int i, int j) {
            int t = p[j];
            p[j] = p[i];
            p[i] = t;
        }

        static void findK(int[] p, int i, int j, int k) {
            if (j <= i) return;
            int p1 = partition(p,i,j);
            if(p1==k-1) {
                //找到了
                return;
            }else if(p1<k-1) {
                //往右边找
                findK(p,p1+1,j,k);
            }else {
                //往左边找
                findK(p,i,p1-1,k);
            }


        }
        static int partition(int[]p,int i,int j) {
            int pivotIndex = ThreadLocalRandom.current().nextInt(i, j + 1);
            int pivot = p[pivotIndex];
            int p1 = i, p2 = j;
            swap(p, p1, pivotIndex);
            while (p1 < p2) {
                while (p1 < p2 && p[p2] >= pivot) {
                    --p2;
                }
                while (p1 < p2 && p[p1] <= pivot) {
                    ++p1;
                }
                if (p1 < p2) swap(p, p1, p2);
            }
            swap(p, p1, i);
            return p1;
        }
        static int quickSelect(int []p,int l,int r,int index) {
            int pivot = partition(p,l,r);
            if(index==pivot) return p[pivot];
            else
            {
                return pivot<index? quickSelect(p,pivot+1,r,index):
                        quickSelect(p,l,pivot-1,index);
            }
        }
    }
}


  1. 最接近原点的 K 个点
    我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。

(这里,平面上两点之间的距离是欧几里德距离。)

你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

import java.util.concurrent.ThreadLocalRandom;

class Solution {
    int[][] points;
    public int[][] kClosest(int[][] points, int K) {
        this.points = points;
        SortUtil.findK(points,0,points.length-1,K-1);
        return Arrays.copyOfRange(points, 0, K);
    }


static class SortUtil {
        static void quickSort(int[] p, int i, int j) {
            if (j <= i) return;
            int pivotIndex = ThreadLocalRandom.current().nextInt(i, j + 1);
            int pivot = p[pivotIndex];
            swap(p, i, pivotIndex);
            int p1 = i, p2 = j;
            while (p1 < p2) {


                while (p1 < p2 && p[p2] >= pivot) {
                    p2--;
                }
                while (p1 < p2 && p[p1] <= pivot) {
                    //p1 跑太过了,导致  p1>=p2 但是, p[p2] >= pivot ,所以,排序不正确,因此,必须要保证 p[p2] >= pivot ,p2跑到最左边
                    p1++;
                }


                if (p1 < p2) {

                    swap(p, p1, p2);
                }
                // System.out.println(Arrays.toString(p)+ " :"+p1+" "+p2);

            }
            swap(p, i, p1);
            quickSort(p, i, p1 - 1);
            quickSort(p, p1 + 1, j);

        }

        static void swap(int[] p, int i, int j) {
            int t = p[j];
            p[j] = p[i];
            p[i] = t;
        }

        
        public static void swap(int[][]points,int i, int j) {
            int t0 = points[i][0], t1 = points[i][1];
            points[i][0] = points[j][0];
            points[i][1] = points[j][1];
            points[j][0] = t0;
            points[j][1] = t1;
        }

        static void findK(int[][] p, int i, int j, int index) {
            if (j <= i) return;
            int p1 = partition(p,i,j);
            if(p1==index) {
                //找到了
                return;
            }else if(p1<index) {
                //往右边找
                findK(p,p1+1,j,index);
            }else {
                //往左边找
                findK(p,i,p1-1,index);
            }


        }

        static int len(int[][]p,int i) {
            return p[i][0]*p[i][0]+
            p[i][1]*p[i][1];    
        }

        static int partition(int[][]p,int i,int j) {
            int pivotIndex = ThreadLocalRandom.current().nextInt(i, j + 1);
            int pivot = len(p,pivotIndex);
            int p1 = i, p2 = j;
            swap(p, p1, pivotIndex);
            while (p1 < p2) {
                while (p1 < p2 && /*p[p2]*/len(p,p2) >= pivot) {
                    --p2;
                }
                while (p1 < p2 && len(p,p1) <= pivot) {
                    ++p1;
                }
                if (p1 < p2) swap(p, p1, p2);
            }
            swap(p, p1, i);
            return p1;
        }
        // static int quickSelect(int[]p,int l,int r,int index) {
        //     int pivot = partition(p,l,r);
        //     if(index==pivot){
        //          return p[pivot];
        //     }
        //     else
        //     {
        //         return pivot<index? quickSelect(p,pivot+1,r,index):
        //                 quickSelect(p,l,pivot-1,index);
        //     }
        // }
    }



    

  
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值