基于快速排序思想的三个算法题

Posted tuke_tuke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于快速排序思想的三个算法题相关的知识,希望对你有一定的参考价值。

一,最小的k个数

输入n个数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8,个数字,则最小的数字是1,2,3,4

基于O(n)的算法,可以用基于Partion函数解决这个问题,如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数组大的所有数字都位于数组的右边,这样调整之后数组左边的k个数字就是最小的k个数字,不一定有序

import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		int k=in.nextInt();
		int[] num=new int[n];
		int[] out=new int[k];
		for(int i=0;i<n;i++){
			num[i]=in.nextInt();
		}
	   boolean b=GetMinK(n,num,k,out);
	   if(b){
		   for(int i=0;i<k;i++){
			   System.out.print(out[i]+" ");
		   }
	   }

	}
	public static boolean GetMinK(int uiInputNum, int[] pInputArray, int uiK, int[] pOutputArray){
		  if(pInputArray==null||pOutputArray==null||uiK>uiInputNum||uiInputNum<=0||uiK<=0){
			 return false; 
		  }
		  int start=0;
		  int end=uiInputNum-1;
		  int index=partition(pInputArray,start,end);
		  while(index!=uiK-1){
			    if(index>uiK-1){//index在k-1的右边
			    	 end=index-1;
			    	 index=partition(pInputArray,start,end);
			    }
			    else{
			    	start=index+1;
			    	index=partition(pInputArray,start,end);
			    }
		  }
		  for(int i=0;i<uiK;i++){
			  pOutputArray[i]=pInputArray[i];
		  }
		  return true;
		  
	}
	//partion分区函数,返回数组a的首元素快排的索引值index
	public static int partition(int[] a,int start,int end){
		  int privot=a[start];
		  int i=start;
		  int j=end;
		  while(i<j){
			  while(i<j&&privot<=a[j]){
				  j--;
			  }
			  swap(a,i,j);
			  while(i<j&&privot>=a[i]){
				  i++;
			  }
			  swap(a,i,j);
		  }
		  return i;
		  
	}
	public static void swap(int[] a,int i,int j){
		int t=a[i];
		a[i]=a[j];
		a[j]=t;
	}
}
二,数组中出现次数超过一半的数字

数组中有一个数字出现次数超过数组长度的一半,请找出这个数字。例如1,2,3,2,2,2,5,4,2,数字2在数组中出现了5次,超过数组长度的一半,输出2

受快速排序的启发,在快速排序中,现在数组中选择一个数字,然后调整数组中的数字的顺序,使得比选中数字小的数字都排在它的左边,比选中数字大的数字都排在它的右边。

如果选中的数字的下标刚好是n/2,那么这个数字就是数组中的中位数

import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		
		int[] num=new int[n];
		
		for(int i=0;i<n;i++){
			num[i]=in.nextInt();
		}
	   int b=GetHalfNum(n,num);
	   if(b!=-1){
		  System.out.println(b);	
	   }

	}
	public static int GetHalfNum(int uiInputNum, int[] pInputArray){
		  if(pInputArray==null||uiInputNum<=0){
			 return -1; 
		  }
		  int middle=uiInputNum>>1;//长度的一半
		  int start=0;
		  int end=uiInputNum-1;
		  int index=partition(pInputArray,start,end);
		  while(index!=middle){//如果不等于长度的一半说明就没有找到这个中位数
			    if(index>middle){
			    	 end=index-1;
			    	 index=partition(pInputArray,start,end);
			    }
			    else{
			    	start=index+1;
			    	index=partition(pInputArray,start,end);
			    }
		  }
		  
		  return pInputArray[index];//index=middle
		  
	}
	
	public static int partition(int[] a,int start,int end){
		  int privot=a[start];
		  int i=start;
		  int j=end;
		  while(i<j){
			  while(i<j&&privot<=a[j]){
				  j--;
			  }
			  swap(a,i,j);
			  while(i<j&&privot>=a[i]){
				  i++;
			  }
			  swap(a,i,j);
		  }
		  return i;
		  
	}
	public static void swap(int[] a,int i,int j){
		int t=a[i];
		a[i]=a[j];
		a[j]=t;
	}
}

三,找出数组中第k个最小的数

例如给定数组1,5,2,6,8,0,6中,第4小的数字是5

import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		int k=in.nextInt();
		int[] num=new int[n];
		//int[] out=new int[k];
		for(int i=0;i<n;i++){
			num[i]=in.nextInt();
		}
	   int b=GetMinK(n,num,k);
	   if(b!=-1){
		  System.out.println(b);	
	   }

	}
	public static int GetMinK(int uiInputNum, int[] pInputArray, int uiK){
		  if(pInputArray==null||uiK>uiInputNum||uiInputNum<=0||uiK<=0){
			 return -1; 
		  }
		  int start=0;
		  int end=uiInputNum-1;
		  int index=partition(pInputArray,start,end);
		  while(index!=uiK-1){//如果index不是k-1的位置
			    if(index>uiK-1){
			    	 end=index-1;
			    	 index=partition(pInputArray,start,end);
			    }
			    else{
			    	start=index+1;
			    	index=partition(pInputArray,start,end);
			    }
		  }
		  
		  return pInputArray[index];//返回的这个位置的数值
		  
	}
	
	public static int partition(int[] a,int start,int end){
		  int privot=a[start];
		  int i=start;
		  int j=end;
		  while(i<j){
			  while(i<j&&privot<=a[j]){
				  j--;
			  }
			  swap(a,i,j);
			  while(i<j&&privot>=a[i]){
				  i++;
			  }
			  swap(a,i,j);
		  }
		  return i;
		  
	}
	public static void swap(int[] a,int i,int j){
		int t=a[i];
		a[i]=a[j];
		a[j]=t;
	}
}

以上是关于基于快速排序思想的三个算法题的主要内容,如果未能解决你的问题,请参考以下文章

基于比较的七种常见排序算法

基于比较的七种常见排序算法

STL六大组件中算法模块sort为啥采用快速排序作为底层思想

排序算法之快速排序

数据结构与算法颜色分类:三路快速排序算法思想实现

交换排序(冒泡排序快速排序的算法思想及代码实现)