【算法导论学习-015】数组中选择第i小元素(Selection in expected linear time)

1、算法思想
问题描述:从数组array中找出第i小的元素(要求array中没有重复元素的情况),这是个经典的“线性时间选择(Selection in expected linear time)”问题。
思路:算法导论215页9.2 Selection in expect linear time
2、java实现
思路:算法导论216页伪代码

/*期望为线性时间的选择算法,输入要求,array中没有重复的元素*/
    public static int randomizedSelect(int[] array,int start,int end,int i) {
        if (start==end) {
            return array[start];
        }
        int middle=randomizedPartition(array, start, end);
        int k=middle-start+1;
        if (i==k) {
            return array[middle];
        }else if (i<k) {
            return randomizedSelect(array, start, middle-1, i);
        }else {
            return randomizedSelect(array, middle+1, end, i-k);
        }
    }
randomizedPartition(array,start,end)参见: 【算法导论-010】快速排序(quickSort)

3、非递归版本

	/*非递归版本的线性时间选择*/
	public static int iterativeRandomizedSelect(int[] array,int start,int end,int i) {
		int result=0;
		while (start<=end) {
			if (start==end) {
				return array[start];
			}
			int middle=randomizedPartition(array, start, end);
			int k=middle-start+1;
			if (i==k) {
				result= array[i];
			} else if (i<k) {
				end=middle-1;
			}else {
				start=middle+1;
				i=i-k;
			}
			
		}
		return result;
	}
*****************************************************************************************************************
扩展一道课后题:《算法导论》P223 9.3-7
 Describe an O(n) algorithm that, given a set S of n distinct numbers and a positive integer k n, determines the k numbers in S that are closest to the median of S.
  翻译过来即:在集合S中选出最接近中位数的k个元素。
  思路:线性选择出第n/2小的元素就是中位数middle,第(n-k)/2的元素low,第(n+k)/2小的元素high,然后遍历整个数组——大于low且小于high且不等于middle的元素就是离middle最近的k个元素。
  
	public static LinkedList<Integer> getClosetToMedian(int[] array,int k) {
		LinkedList<Integer> linkedList=new LinkedList<Integer>();
		int n=array.length;
		int median=randomizedSelect(array, 0, n-1, n/2);
		int low=randomizedSelect(array, 0, n-1, (n-k)/2);
		int high=randomizedSelect(array, 0, n-1, (n+k)/2);
		for (int i : array) {
			if (i>=low&&i<=high&&i!=median) {
				linkedList.add(i);
			}
		}
		return linkedList;
	}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值