215. 数组中的第K个最大元素 快排思想+小根堆

215. 数组中的第K个最大元素

难度:中等
题目描述
在这里插入图片描述
解题思路

1、排序

最简单最偷懒的当然是先排序,然后返回第n-k个元素,轻轻松松通过题数+1

public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        int n = nums.length;
        return nums[n-k];

    }

在这里插入图片描述

2、维护一个大小为k的堆

用优先队列来实现小根堆,堆顶是k个元素里最小的,k个数字之外,如果数字大于堆顶,就丢掉堆顶元素,加入新元素。

/*
		  * 215. 数组中的第K个最大元素
		  * 2020/6/29每日一题打卡  用优先队列实现小根堆(根比节点要小)
		  */
		 public int findKthLargest(int[] nums, int k) {
			 int n = nums.length;
			 PriorityQueue<Integer> minHeap = new PriorityQueue<>((a,b) -> a - b);
			 for(int i = 0; i < k; i++){
				 minHeap.offer(nums[i]);
			} 
			 for (int i = k; i < n; i++) {  //如果大于当前堆顶
				if(minHeap.peek() < nums[i]) {
					minHeap.poll();
					minHeap.offer(nums[i]);
				}
			}
			 return minHeap.peek();

		    }

在这里插入图片描述

3、利用快排划分思想

快排的思想就是每次选取一个基准,以这个基准为划分,比这个数小的放左边,比这个数大的放右边。修改快排的划分方法,每次返回基准元素的下标,要找的数下标应该是n-k,所以如果返回的下标大于n-k,就继续划分右边;如果小于n-k,划分右边。
为了防止快排中存在的递归退化问题,每次不选择最左边的为基准,以中间元素为基准。(加了这个之后从16ms提高到了1ms)

 	public int findKthLargest(int[] nums, int k) {
			 return quickSelect(nums, 0, nums.length - 1, nums.length - k);
		    }
	 public int quickSelect(int[] a, int l, int r, int index) {
	        int q = partition(a, l, r);
	        if (q == index) {
	            return a[q];
	        } else {
	            return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
	        }
	    }
		public int partition(int nums[],int low,int high) {
			if(low > high){
	            return -1;
	        }
               int p = (low + high) / 2;
               swap(nums,low,p);
			int i = low,j = high;
			int target = nums[low];
			while(i < j) {
				while(nums[j] >= target && i < j) {
					j--;
				}
				while(nums[i] <= target && i < j) {
					i++;
				}
				if(i < j)
					swap(nums, i, j);
			}
			if(i != low)
				swap(nums, i, low);	
			return i;
		}
		public void swap(int[] nums,int a,int b) {
			int temp = nums[a];
			nums[a] = nums[b];
			nums[b] = temp;
		}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值