算法~寻找最K大的数

如果是一个有序数组,那么寻找第k的大数则相当简单了,且效率为1。数组排序算法中相对较优的算法为快速排序,效率为N*lgN,将数组从到到小排列,第k大的数则为array[k-1]。

1.快速排序
快排的思想为:从数组中取任意一个值key,将大于key的值放在key右边,小于key的值放在key左边。key的左边和右边则都是有序的了,然后递归key左边的子数组和key右边的子数组,直到每个子数组长度为1,此时,整个数组均有序了。

package adv;


import java.util.Arrays;
public class Main {

   public static void main(String[] args) {

	      int arr[]= {65,58,95,10,57,62,13,106,78,23,85};

	      System.out.println("排序前:"+Arrays.toString(arr));

	      quickSort(arr,0,arr.length-1);

	      System.out.println("排序后:"+Arrays.toString(arr));

	   }
	
	public static void quickSort(int[] nums, int left, int right) {
		int pivot = 0;
		if(left<right) {
			pivot = partition(nums, left, right);
			quickSort(nums, left, pivot-1);
			quickSort(nums, pivot+1, right);
		}
	}
	
	public static int partition(int[] nums, int left, int right) {
		int key = nums[left];
		while(left<right) {
			while(left<right && nums[right]>=key) {
				right--;
			}
			nums[left] = nums[right];
			while(left<right && nums[left]<=key) {
				left++;
			}
			nums[right] = nums[left];
		}
		nums[left] = key;
		return left;
		
	}
}

2.类快排解法
由于只要求找出第k大的数,没必要将数组中所有值都排序。

快排中的partition算法,返回key在数组中的位置,如果key的位置正好等于k-1,那么问题则得到解决,如果key的位置不等于k-1,可使用递归查找对应子数组。直到key的位置等于k-1,则找对问题的解。

package adv;


import java.util.Arrays;
public class Main {

   public static void main(String[] args) {

	      int arr[]= {65,58,95,10,57,62,13,106,78,23,85};

	      System.out.println("排序前:"+Arrays.toString(arr));

	      int k = findK(arr,0,arr.length-1,5);

	      System.out.println("排序后:"+Arrays.toString(arr));

	      System.out.println("第K大的数字: " + k);
	   }
	
   public static int findK(int[] nums, int left, int right, int k) {
	    int i = partition(nums, left, right);
	    if (i == k - 1) {
	        return nums[k - 1];
	    } else if (i > k - 1) {
	        return findK(nums, left, i - 1, k);
	    } else if (i < k - 1) {
	        return findK(nums, i + 1, right, k);
	    }
	    return 0;
   }
	
	public static int partition(int[] nums, int left, int right) {
		int temp = nums[left];
		while(left<right) {
			//右侧
			while(left<right && nums[right]>=temp) {
				right--;
			}
			nums[left] = nums[right];
			//左侧
			
			while(left<right && nums[left]<=temp) {
				left++;
			}
			nums[right] = nums[left];
			//左侧
		}
		nums[left] = temp;
		return left;
		
	}
}
/*
排序前:[65, 58, 95, 10, 57, 62, 13, 106, 78, 23, 85]
排序后:[10, 13, 23, 57, 58, 62, 65, 106, 78, 95, 85]
第K大的数字: 58
*/

https://blog.youkuaiyun.com/bandaoyu/article/details/84706044

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值