次序选择问题 java代码完整实现 分治法

什么是次序选择:

就是需要找出给定序列中第k小元素(其中k大于等于1小于等于n)。
比如当k=3时,我们需要找出该序列中第三小元素。

分治法解决次序选择问题:

我们可以借用随机主元的快速排序的思维去解决该问题(点击查看本人另一篇博文随机化快速排序:随机化快速排序),与快速排序不同的是,在主元下标等于k时,我们就可以直接退出,不需要再进行剩下的分解问题和合并问题解过程。其时间复杂度的数学期望为O(n),是一个非常高效的算法。
比如我们要寻找第4小元素,给定数组为945721683,下面我们对其进行分析:
开始——>(比主元大的用蓝色表示,比主元小的用橙色表示,i指向数组首端的前一个,j指向数组首端,即i=left-1,j=left).
刚开始i指向空,j指向9.
1.随机选择主元,假设选择主元为6;
2.主元6与末尾3交换,变为:945721386
3.主元6与j所指9比较,比6小,j++,j指向4,数组变为:945721386
4.主元6与j所指4比较,比4大,i++,i此时指向9,i与j交换,j++,变为:495721386
5.主元6与j所指5比较,比5大,i++,i此时指向9,i与j交换,j++,变为:459721386
6.主元6与j所指7比较,比7小,j++,变为:457921386
7…省略2138的比较与上述类似,变为:452139786
8.j指向了数组最后一个,即主元,则i+1与主元交换,即9与主元6交换
9.然后判断第4小元素,即k=4与主元下标i+1的大小,若k<i+1,则选取左半边重复上述过程;如果k>i+1,则选取右半边重复上述过程.
直到交换后的主元下标等于k。

代码部分:

public void toSelection(int []arr,int left,int right,int k) {
	int principalElement = left+(int)(Math.random()*(right-left+1));  //选取随机主元
	//把随机主元放到数组尾部
	int temp = arr[principalElement];
	arr[principalElement] = arr[right];
	arr[right] = temp;
	int i = left -1;
	for(int j = left;j<right;j++) {
		if(arr[j]<arr[right]) {
			++i;
			int temp1 = arr[j];
			arr[j] = arr[i];
			arr[i] = temp1;
		}
	}
	int temp2 = arr[right];
	arr[right] = arr[i+1];
	arr[i+1] = temp2;
	
	if(k == i+1)
		System.out.print("第"+(k+1)+"小数为:"+arr[k]);
	if(k<i+1)
		toSelection(arr,left,i,k);
	if(k>i+1)
		toSelection(arr, i+2, right, k);
}

函数调用,运行结果:

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/MrYushiwen/article/details/107279359