桶排序和最优连续子序列使用分治算法-java实现

124 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

桶排序

桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

图片.png

代码

package test1;
import java.util.Arrays;
/**
 * @author 小徐同学
 *
 * 2021年10月30日
 */
public class BucketSort {

	public static void basket(int data[])//data为待排序数组
	    {
	          int n=data.length;
	          int bask[][]=new int[10][n];
	          int index[]=new int[10];
              int max=Integer.MIN_VALUE;
	        for(int i=0;i<n;i++)
	    {
	          max=max>(Integer.toString(data[i]).length())?max:(Integer.toString(data[i]).length());
	}
	          String str;
        for(int i=max-1;i>=0;i--){
	        for(int j=0;j<n;j++){
	           str="";
	        if(Integer.toString(data[j]).length()<max){
	            for(int k=0;k<max-Integer.toString(data[j]).length();k++)
	                 str+="0";
	}
	             str+=Integer.toString(data[j]);
	           bask[str.charAt(i)-'0'][index[str.charAt(i)-'0']++]=data[j];
 	}
            	int pos=0;
	     for(int j=0;j<10;j++){
	 for(int k=0;k<index[j];k++){
	       data[pos++]=bask[j][k];
  }
	}
	for(int x=0;x<10;x++)index[x]=0;
	}
}
	public static void main(String [] args){
		int [] arr ={99,55,44,33,20,11,25,69,50};
		System.out.println("排序前:"+Arrays.toString(arr));
		basket(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

结果

排序前:[99, 55, 44, 33, 20, 11, 25, 69, 50] 排序后:[11, 20, 25, 33, 44, 50, 55, 69, 99]

求最优连续子序列 使用分治算法

这种比较难以理解,是使用分治的这种思想很多动态规划算法非常像数学中的递推。我们如果能找到一个合适的递推公式,就能很容易的解决问题。

package test1;
/**
 * @author 小徐同学
 *
 * 2021年10月30日
 */
public class test{
	public static int matrixChain(int[] p, int[][] m, int[][] s) {
		int n = p.length - 1;
		for (int i = 1; i <= n; i++)
			// 本身为0
			m[i][i] = 0; 
		for (int r = 2; r <= n; r++) {
			for (int i = 1; i <= n - r + 1; i++) { 
				int j = i + r - 1;
				m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];  // 求出Ai到Aj的连乘
				s[i][j] = i;  // 记录划分位置
				for (int k = i + 1; k < j; k++) {// 寻找是否有可优化的分割点
					int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];  // 公式
					if (t < m[i][j]) {
						m[i][j] = t;
						s[i][j] = k;
					}
				}
			}
		}
		return m[1][n];
	}
	/**
	 * 输出 A[i:j] 的最优计算次序
	 * @param i、j: 连乘矩阵下标
	 * @param s: 存放分割位置下标的数组
	 **/
	public static void traceback(int i, int j, int[][] s) {
		// 输出A[i:j] 的最优计算次序
		if (i == j) {
			// 递归出口
			System.out.print("A"+i);
			return;
		} else {
			System.out.print("(");
			// 递归输出左边
			traceback(i, s[i][j], s);
			// 递归输出右边
			traceback(s[i][j] + 1, j, s);
			System.out.print(")");
		}
	}
	public static void main(String[] args) {
		int[] p = new int[]{35,15, 5, 10, 20};
		int[][] m = new int[p.length][p.length];
		int[][] s = new int[p.length][p.length];
		System.out.println("最优值为: "+matrixChain(p, m, s));
		traceback(1, p.length-1, s);
	}
}

结果

最优值为: 7125 ((A1A2)(A3A4))