算法经典问题:设有一组N个数而要确定其中第k个最大者,我们称之为选择问题(selection problem)。下面我提供两种简单的算法来解决这个问题:
package selection_problem;
import java.util.LinkedList;
import java.util.List;
/**
* @ClassName: CommonUtils
* @Description: 公共的工具类
* @author Shockang
* @date 2017年5月1日 上午12:06:40
*/
public class CommonUtils
{
/**
* @Title: bubbleSort
* @Description: 冒泡排序
* @param array
* @return double[]
* @throws
*/
public static double[] bubbleSort(double[] array)
{
for (int i = 0; i < array.length-1; i++ )
{
for (int j = 0; j < array.length - i - 1; j++ )
{
if (array[j] < array[j + 1])
{
double temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
/**
* @Title: object2Double
* @Description: Object[]转化成Double[]
* @param array
* @return double[]
* @throws
*/
public static double[] object2Double(Object[] array)
{
double[] doubleArrray = new double[array.length];
for (int i = 0; i < array.length; i++ )
{
doubleArrray[i] = (double)array[i];
}
return doubleArrray;
}
/**
* @Title: array2List
* @Description: 数组转化成list
* @param array
* @return List<Double>
* @throws
*/
public static List<Double> array2List(double[] array)
{
List<Double> doubleList = new LinkedList<>();
for (double d : array)
{
doubleList.add(d);
}
return doubleList;
}
/**
*
* @Title: str2Double
* @Description: String[]转化成double[]
* @param str
* @return double[]
* @throws
*/
public static double[] str2Double(String[] str)
{
double[] d=new double[str.length];
for(int i=0;i<str.length;i++)
{
d[i]=Double.parseDouble(str[i]);
}
return d;
}
}
package selection_problem;
import java.util.List;
/**
*
* @ClassName: Solution1
* @Description: 将这N个数读进一个数组中,再通过冒泡排序法,以递减顺序将数组排序,然后返回位置k上的元素
* @author Shockang
* @date 2017年4月30日 下午10:26:26
*
*/
public class Solution1
{
public static double toSelect(List<Double> numList, int k)
{
double[] numArray = CommonUtils.object2Double(numList.toArray());
return CommonUtils.bubbleSort(numArray)[k-1];
}
}
package selection_problem;
import java.util.List;
/**
* @ClassName: Solution2
* @Description: 把前k个元素读入数组并以递减顺序排序,然后将剩下元素逐个读入,挤掉数组中原来的元素(保证数组中最后只剩下最大的k位元素),最后,返回位于第k个位置上的元素
* @author Shockang
* @date 2017年4月30日 下午10:33:03
*/
public class Solution2
{
public static double toSelect(List<Double> numList, int k)
{
double[] doubleArray = list2Array(numList, k);
doubleArray = CommonUtils.bubbleSort(doubleArray);
List<Double> doubleList = CommonUtils.array2List(doubleArray);
doubleList = crush(numList, doubleList, k);
return doubleList.get(k - 1);
}
private static double[] list2Array(List<Double> numList, int k)
{
double[] doubleArray = new double[k];
for (int i = 0; i < k; i++ )
{
doubleArray[i] = numList.get(i);
}
return doubleArray;
}
private static List<Double> crush(List<Double> numList, List<Double> doubleList, int k)
{
for (int i = k; i < numList.size(); i++ )
{
for (int j = 0; j < k - 1; j++ )
{
if (numList.get(i) < doubleList.get(j) && numList.get(i) > doubleList.get(j + 1))
{
doubleList.remove(k - 1);
doubleList.add(j + 1, numList.get(i));
}
else if (numList.get(i) > doubleList.get(0))
{
doubleList.remove(k - 1);
doubleList.add(0, numList.get(i));
}
}
}
return doubleList;
}
}
package selection_problem;
import java.util.List;
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.println("请输入N个数(不少于5个),以','为分隔符");
String inStr = sc.nextLine();
sc.close();
String[] strArray = inStr.split(",");
double[] doubleArray=CommonUtils.str2Double(strArray);
List<Double> numList=CommonUtils.array2List(doubleArray);
int k=5;
long time1=System.nanoTime();
System.out.println("方法1所得的结果为:"+Solution1.toSelect(numList, k));
long time2=System.nanoTime();
System.out.println("方法1的运行时间为:"+String.valueOf(time2-time1)+" ns");
long time3=System.nanoTime();
System.out.println("方法2所得的结果为:"+Solution2.toSelect(numList, k));
long time4=System.nanoTime();
System.out.println("方法2的运行时间为:"+String.valueOf(time4-time3)+" ns");
}
}
控制台输出:
请输入N个数(不少于5个),以','为分隔符
1,2,3,4,5,6,7,8,9,10.1,10.5,11,15,18,21,20.4
方法1所得的结果为:11.0
方法1的运行时间为:4192667 ns
方法2所得的结果为:11.0
方法2的运行时间为:1930340 ns
请输入N个数(不少于5个),以','为分隔符
1.1,2.1,4.1,3,5,8,7,9,15,11,25,14,15.6,35.4,35.1,69,12,34,9,8.5,6.2
方法1所得的结果为:25.0
方法1的运行时间为:4566894 ns
方法2所得的结果为:25.0
方法2的运行时间为:1914156 ns
可以明显看出,从运行时间角度来讲,方法2的效率更高。
以上代码均为原创,不足之处敬请指教,下次带来效率更高的算法。