分治算法-线性时间选择

				## 分治法之线性时间选择问题

以前没写过博客,这学期开设了一门算法设计与分析的课程,老师给我们讲了CSDN的重要性,是我们IT人士共享交流的平台,在上面可以看到很多大神的经验分享,所以我也来加入这个行列啦 哈哈哈

分治法的基本思想

这几天都在学习分治算法,何为分值算法呢,其主要的思想就是将一个问题规模为N的问题,然后将其划分为k个相同的子问题,使每个子问题都具有最优子结构,子问题是相互独立的。然后我们就递归的解决这些子问题,然后自底向上合并每个子问题的解,最后得到的一个解就是我们问题所求的解了。

分治法的一般算法模式

divide-and-conquer(P){
     
	if(|p|<=n) //|P|是问题规模,n是出口,表示问题规模不超过n时,问题						   容易解决
		adhoc(P); //问题规模不超过n时,直接用算法adhoc(P)解决
	divide P into smaller subinstances P1,P2,..Pk;
	for(i=1;i<=k;i++){
     
		yi=divide-and-conquer(Pi);	
	}
	return merge(y1,y2,...yk);  //merge()合并子问题的解
}

线性时间选择问题

好啦,讲了分治法的基本思想,那我们就来看看线性时间选择问题吧
问题描述:找一个数组中第k小元素。
例子:数组a={2,20,7,1,9,3,10,15,8,4}
输入:k=6
输出:8

问题分析:这道题沿用了快速排序的思想,(这里小周周就当你们学会了快速排序啦) 只不过只对一个子序列操作。当k比左边子序的长度小时,说明要找的元素在左子序列,然后就舍去右子序列,只对左子序列继续同样的操作,否则,如果K大于左边子序列的长度时。说明要找的元素在右子序列中,然后就舍去左子序列,只对右子序列继续同样的操作。对右子序列操作时,我们要更改k,将k变为在右子序列中第几小元素。比如数组a包含1到10,10个自然数,然后要查找的k=6时,因为k大于左边子序列长度(10/2=5),所以在右边子序列查找,但是k就要变为在右子序列中第1小元素了(k=k-5=6-5=1)。当序列只剩一个元素时,这个元素就是我们要查找的第K小元素了。

代码如下所示:(java)

import java.util.*;
public class XianXing {
     
	static int k; //要查找的第几小元素 设置为静态的(共享的) 可以在任何地方修改值
	static int z=1; //统计sort函数调用次数
	static int y=1; //统计partition函数调用次数
	public static void main(String[] args) {
     
		Scanner s=new Scanner(System.in);
		System.out.print("请输入要查找第几小元素:");
		k=s.nextInt();
		int []a= {
     12,38,1,3,89,100,2,7,29,28,43,78,28,11,4};
		sort(a,0,a.length-1);
	}
	public static void sort(int []a,int l,int r) {
     
		System.out.println("这是第 "+z+" 次调用sort函数 进来的l是:"+l+"进来的r是:"+r);
		z++;
		if(l==r) {
      //当只剩一个元素时,该元素就是要查找的第几最小元素
			System.out.println("该元素为:"+a[l]);
		}
		if(l<r) {
     
			int mid=partition(a,l,r);  
			if(k<=mid-l+1) {
      //(mid-l+1)是左边子序列的长度,当K<=左边子序列的长度时,说明第几最小元素在左边子序列
				sort(a,l,mid);
			}else {
     	//当K>左边子序列的长度时,说明第几最小元素在右边子序列
				k=k-(mid-l+1);   //并且k变为了在右边子序列中第k-(mid-l+1)最小元素
				sort(a,mid+1,r);
			}
		}
	}
	public static int partition(int []a,int l,int r) {
     
		int i=l;
		int j=r+1;
		int x=a[l];  //基准元
		System.out.println("这是第 "+y+" 次调用partition函数 进来的l是:"+l+"进来的r是:"+r);
		y++;
		while(true) {
       //java中只能是true
			while(a[++i]<x&&i<r);  //寻找左边比基准元大的元素
			while(a[--j]>x); //寻找右边比基准元小的元素
			if(i>=j) {
      //i对应左半部分,j对应右半部分
				break;
			}
			swap(a,i,j);  //交换左边比基准元素大的元素和右边比基准元素小的元素
		}
		a[l]=a[j]; //更改基准元 使得基准元左边的数都比基准元小,右边的数都比基准元大
		a[j]=x;    
		return j;  //返回基准元下标
	}
	public static void swap(int []a,int i,int j) {
     
		int temp;
		temp=a[i];
		a[i]=a[j];
		a[j]=temp;
	}
}

运行结果如下:

测试数组a={12,38,1,3,89,100,2,7,29,28,43,78,28,11,4} k=7
分治算法-线性时间选择_第1张图片

好啦,线性时间选择问题我们就聊到这啦,有什么不懂得话记得私聊小周周我呢。
如果你们喜欢的话,别忘了给小周周点个赞哦,小公举们的满意,是小周周无尽的动力!❥(^_-)
【无名之辈 我是谁 小小的天 也有大大的梦想】

你可能感兴趣的:(笔记,算法,分治算法)