leetcode-215-数组中的第K个最大元素 (kth largest element in an array)-java

版权声明:此文章为许诗宇所写,如需转载,请写下转载文章的地址 https://blog.csdn.net/xushiyu1996818/article/details/84950735

题目及测试

package pid215;
/*数组中的第K个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

*/


public class main {
	
	public static void main(String[] args) {
		int[][] testTable = {{1,2,3,2},{1,2,3,4},{1,1,1,3,3,4,3,2,4,2},{3,2,1,5,6,4}};
		for (int[] ito : testTable) {
			test(ito,2);
		}
	}
		 
	private static void test(int[] ito,int k) {
		Solution solution = new Solution();
		int rtn;
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ito.length; i++) {
		    System.out.print(ito[i]+" ");		    
		}
		System.out.println();
		//开始时打印数组
		
		rtn = solution.findKthLargest(ito,k);//执行程序
		long end = System.currentTimeMillis();	
		
		//System.out.println(ito + ": rtn=" + rtn);
		System.out.println(": rtn=" +rtn);
		
		
		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}

}

解法1(成功,4ms,超快)

使用最小堆的方法,求第k大,建立一个规模为k的最小堆

首先将nums前k个元素加入堆,然后初始化最小堆,让heap[0]为这k个元素小的

然后将nums第k到length-1个,依次与heap[0]比较
如果比它大,则替代heap【0】,然后下沉,让heap[0]继续是这k个最小的
所以最后,heap为nums中前k大的,heap[0]为第k大的

该方法速度为o(nlogk),比全部排序o(nlogn)快

package pid215;

import java.util.Arrays;

import javax.naming.InitialContext;

public class Solution {
public int findKthLargest(int[] nums, int k) {
    int length=nums.length;
    int[] heap=new int[k];
    for(int i=0;i<k;i++){
    	heap[i]=nums[i];
    }
    //先建立一个最小堆
    for(int i=k-1;i>=0;i--){
		upAdjust(heap,i,k);
	}
    //将其他的数与最小堆的顶部比较,比它大则替代顶部,然后下沉
    for(int i=k;i<length;i++){
    	int now=nums[i];
    	if(now<=heap[0]){
    		continue;
    	}
    	else{
    		heap[0]=now;
    		downAdjust(heap, 0, k);
    	}
    }	
	return heap[0];
    }

	//调整i位和它的子节点的大小,使小的上浮
	public static void upAdjust(int[] nums,int i,int length){
		int left=2*i+1;
		int right=2*i+2;
		if(left<length&&nums[left]<nums[i]){
			swap(nums, i, left);
		}
		if(right<length&&nums[right]<nums[i]){
			swap(nums, i, right);
		}
		if(left<length){
			upCheck(nums, left, length);
		}
		if(right<length){
			upCheck(nums, right, length);
		}
		
		
	}
	public static void upCheck(int[] nums,int i,int length){
		int left=2*i+1;
		int right=2*i+2;
		if((left<length&&nums[left]<nums[i])||(right<length&&nums[right]<nums[i])){
			upAdjust(nums, i, length);
		}
			
	}
	
	public static void downAdjust(int[] nums,int i,int length){
		int left=2*i+1;
		int right=2*i+2;
		if(left<length&&nums[left]<nums[i]&&(right>=length||(right<length&&nums[left]<=nums[right]))){
			swap(nums, i, left);
			downAdjust(nums, left, length);
		}
		if(right<length&&nums[right]<nums[i]&&nums[left]>nums[right]){
			swap(nums, i, right);
			downAdjust(nums, right, length);
		}
	}
	public static void swap(int[] nums,int i,int j){
		int temp=nums[i];
		nums[i]=nums[j];
		nums[j]=temp;
	}
}

解法2(别人的)

利用快速排序的思想,在进行排序过程中每次可以确定一个元素的最终位置,若此位置为第K个最大元素,则直接返回此索引,否则继续分治进行快速排序。不用排列全部,只要每次只排序一段,找到即可

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int begin=0;
        int end=nums.length-1;
         k=nums.length+1-k;
         while(begin<end){
            int pos=partition(nums,begin,end);
            if(pos==k-1) break;
            else if(pos<k-1) begin=pos+1;
            else end=pos-1;
        }
        return nums[k-1];
    }
    public int partition(int[]nums,int l,int r){
          int less=l-1;//小于区的下标
          int  more=r;//大于区的下标,默认以最后一个下标的数作为划分值
          while(l<more){
              if(nums[l]<nums[r])
                 swap(nums,++less,l++);
              else if  (nums[l]>nums[r]) 
                 swap(nums,--more,l);
              else l++;
          }
          swap(nums,more,r);
          return less+1;//小于区位置+1可以得到划分的这个数的下标
      }
    private void swap(int[] a, int i, int j) {
          int t = a[i];
          a[i] = a[j];
          a[j] = t;
    }
}

猜你喜欢

转载自blog.csdn.net/xushiyu1996818/article/details/84950735
今日推荐