数据结构与算法分析(java语言描述)

第一章 引论

1.1 本书讨论的内容

确定N个数中第k大的数

  设有一组N个数而要确定其中第k个最大者,我们称之为选择问题。书中介绍了两种解法:
  一是将这N个数读进一个数组中,再通过某种简单的算法,比如冒泡排序法,以递减顺序将数组排序,然后返回位置k上的元素;
  二是可以把前k个元素读入数组并(以递减的顺序)对其排序。接着,将剩下的元素再逐个读入。当新元素被读到时,如果它小于数组中的第k个元素则忽略之,否则就将其放到数组中正确的位置上,同时将数组中的一个元素挤出数组。当算法终止时,位于第k个位置上的元素作为答案返回。
  第一种解法很容易就写出来了,但是第二种解法着实使我耗费了很久的时间,而且搞得我晕头转向的。
  第二种解法我按照错误的思路写了很久,我认为取出数组的前k个数后,用剩余的N-k个数和k数组(初始数组的前k个数组成的数组)里的数从大到小、逐个地进行比较,只要在k数组里找到比该数小的数,就即刻替换更新k数组。这种思路的错误在于,被替换的数,本身可能是一个很大的数,实际在N数组(初始数组)中是排的上前k位的,却仅仅因为比剩余数里的一个数小,就被踢出了排位,而原先在k排位中比它小的数却侥幸留存了下来,这就是错误的根源。如:原数组[1, 2, 3, 4, 5, 6, 7, 8, 9],确定第4大的数,先取出前4个元素并从大到小排序组成k数组[4, 3, 2, 1],剩余的数构成数组[5, 6, 7, 8, 9]。读取剩余数组中的数更新k数组,更新的过程为:

5—> [5, 3, 2, 1]
6—> [6, 3, 2, 1]
7—> [7, 3, 2, 1]
8—> [8, 3, 2, 1]
9—> [9, 3, 2, 1]

  最后k数组为[9, 3, 2, 1],第4大的数为1.错误!
  正确的做法应该是在得到剩余数组里的数在k数组的正确排序后,把k数组里数往后移动。正确的更新过程应该是:

5—> [5, 4, 3, 2]
6—> [6, 5, 4, 3]
7—> [7, 6, 5, 4]
8—> [8, 7, 6, 5]
9—> [9, 8, 7, 6]

  最后k数组应为[9, 8, 7, 6],第4大的数为6.
  结论:不能直接替换k数组里的数,要先向右复制更新k数组后再替换。

/* 问题:一个有N个数的数组,确定其中第K个最大值
 * 1。生成一个整数数组,存放随机数
 * 2.写两个函数,分别为冒泡排序和读入前K个数
 */
public class SelectionProblem {
   
	public static void main(String[] args) {
   
		int n = 100000;
		int[] arr = new int[n];
		for(int i = 0; i < n; i++){
   
			int number = (int)(Math.random()*100);
			arr[i] = number;
		}
		//复制数组,用于另一种方法
		int[] arr2 = new int[n];
		for(int i = 0; i < n; i++){
   
			arr2[i] = arr[i];
		}
		long start;
		long end;
		start = new Date().getTime();
		System.out.println(bubble(arr, 5000));
		end = new Date().getTime();
		System.out.printf("冒泡法花了%d秒\n", (end - start)/1000);
		System.out.println(firstK(arr2, 5000));
		start = new Date().getTime();
		System.out.printf("读取前k个数法花了%d秒", (start - end)/1000);
	}
	
	public static int bubble(int[] arr, int k){
   
		for(int i = 0; i < arr.length; i++){
   
			for(int j = 0; j < arr.length - i -1; j++){
   
				if(arr[j] < arr[j + 1]){
   
					int temp = arr[j + 1];
					arr[j + 1] = arr[j];
					arr[j] = temp;
				}
			}
		}
		return arr[k - 1]; 
	}
	
	public static int firstK(int[] arr, int k){
   
		int[] collection = new int[k];
		int[] rest = new int[arr.length-k];
		System.arraycopy(<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值