首页 > 代码库 > 关于分治算法的个人理解
关于分治算法的个人理解
关于分治算法的个人理解:
把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
以快速排序为例,先取一个参数。将大于该参数的值放在右边,小于该参数的值放在左边,使该参数处于最正确的位置上。
该案例的基本思想:是将该数组排序问题分成为该数组中的数值与选取的参数值比较大小。即简单的一对一的比较问题。
该比较问题相互独立、具有最优子结构性质,且可以合并。
1.快速排序
public class Test{
public static void main(String []args){
int arr[] = {40,30,15,57,86,68,98};
quick(arr , 0 , arr.length-1);
for(int i:arr){
System.out.print(i+" ");
}
}
public static void quick(int[] arr , int min , int max){
if(min < max){
int n = sort(arr , min , max);
quick(arr , min , n-1);
quick(arr , n+1 , max);
}
}
public static int sort(int[] arr , int min , int max){
int sum = arr[min];
while(min < max){
while(min < max && arr[max] >= sum){
max--;
}
arr[min] = arr[max];
while(min < max && arr[min] <= sum){
min++;
}
arr[max] = arr[min];
}
arr[min] = sum;
return min;
}
}
二分搜索:
public class Test{
public static void main(String []args){
int []arr = {0,1,3,5,7,8,9};
System.out.println(select(arr,0,arr.length-1,3));
}
public static int select(int[] arr , int min , int max , int i){
while(min <= max){
int middle = (min + max)/2;
if(i == arr[middle]){
return middle;
}else if(i<arr[middle]){
return select(arr,min,middle - 1,i);
}else{
return select(arr,middle + 1,max,i);
}
}
return -1;
}
}
汉诺塔:
public class Test {
public static void main(String []args){
move(3,"A","B","C");
}
public static void move(i,String A, Sting B, String C){
if(i==1){
System.out.println("把"+i+"从"+A+"移动到"+C);
}else{
move(i-1,A,C,B);
System.out.println("把"+i+"从"+A+"移动到"+C);
move(i-1,B,A,C);
}
}
}
矩阵相加:
public class Test{
public static void main(String []args){
int[][] a = {{1,2},{3,4}};
int[][] b = {{5,6},{7,8}};
int[][] c = new int[a.length][b.length];
if( a.length != b.length){
System.out.println();
}else{
for(int i=0;i<a.length;i++){
for(int j=0;i<b.length;j++){
c[i][j] = a[i][j] + b[i][j];
}
}
}
}
}
矩阵相减:
public class Test{
public static void main(String []args){
int[][] a= {{1,2},{3,4}};
int[][] b= {{5,6},{7,8}};
int[][] c = new int[a.length][b.length];
if( a.length != b.length){
System.out.println();
}else{
for(int i=0;i<a.length;i++){
for(int j=0;i<b.length;j++){
c[i][j] = a[i][j] - b[i][j];
}
}
}
}
}
矩阵相乘(简单直接):
public class Test{
public static void main(String []args){
int[][] a= {{1,2},{3,4}};
int[][] b= {{5,6},{7,8}};
int[][] c = new int[a.length][b.length];
if( a.length != b.length){
System.out.println("您输入的矩阵不正确!!!");
}else{
for(int i=0;i<a.length;i++){
for(int j=0;i<b.length;j++){
c[i][j] = 0;
for(int k=0;k<c.length;k++){
c[i][j] += a[i][k]*b[k][j]
}
}
}
}
}
}
矩阵相乘(利用分治思想):
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [][]a = {{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}};
int [][]b = {{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}};
int [][]c = flag(a,b,a.length);
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c.length; j++) {
System.out.print(c[i][j] + "\t");
}
System.out.println();
}
}
private static int[][] flag(int[][] a, int[][] b, int n) {
int[][] result = new int[n][n];
if (n == 1) {
result[0][0] = a[0][0]*b[0][0];
return result;
}
int [][]a11 = new int[n/2][n/2];
int [][]a12 = new int[n/2][n/2];
int [][]a21 = new int[n/2][n/2];
int [][]a22 = new int[n/2][n/2];
int [][]b11 = new int[n/2][n/2];
int [][]b12 = new int[n/2][n/2];
int [][]b21 = new int[n/2][n/2];
int [][]b22 = new int[n/2][n/2];
//将矩阵A分块
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
a11[i][j] = a[i][j];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
a12[i][j] = a[i][j+n/2];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
a21[i][j] = a[i+n/2][j];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
a22[i][j] = a[i+n/2][j+n/2];
}
}
//将矩阵A分块
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
b11[i][j] = b[i][j];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
b12[i][j] = b[i][j+n/2];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
b21[i][j] = b[i+n/2][j];
}
}
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
b22[i][j] = b[i+n/2][j+n/2];
}
}
//求出各分块的相加与相减的值
int[][] s1 = del(b12,b22,n/2);
int[][] s2 = add(a11,a12,n/2);
int[][] s3 = add(a21,a22,n/2);
int[][] s4 = del(b21,b11,n/2);
int[][] s5 = add(a11,a22,n/2);
int[][] s6 = add(b11,b22,n/2);
int[][] s7 = del(a12,a22,n/2);
int[][] s8 = add(b21,b22,n/2);
int[][] s9 = del(a11,a21,n/2);
int[][] s10 = add(b11,b12,n/2);
//求出该运算中的7次乘法
int[][] M1 = flag(a11,s1,n/2);
int[][] M2 = flag(s2,b22,n/2);
int[][] M3 = flag(s3,b11,n/2);
int[][] M4 = flag(a22,s4,n/2);
int[][] M5 = flag(s5,s6,n/2);
int[][] M6 = flag(s7,s8,n/2);
int[][] M7 = flag(s9,s10,n/2);
//做最后的加减
int[][] C11 = add(del(add(M5,M4,n/2),M2,n/2),M6,n/2);
int[][] C12 = add(M1,M2,n/2);
int[][] C21 = add(M3,M4,n/2);
int[][] C22 = del(del(add(M5,M1,n/2),M3,n/2),M7,n/2);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++) {
if(i < n/2) {
if(j < n/2){
result[i][j] = C11[i][j];
}else{
result[i][j] = C12[i][j-n/2];
}
}else {
if(j < n/2){
result[i][j] = C21[i-n/2][j];
}else{
result[i][j] = C22[i-n/2][j-n/2];
}
}
}
return result;
}
private static int[][] add(int[][] a, int[][] b, int n) {
int[][] result = new int[n][n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
result[i][j] = a[i][j] + b[i][j];
}
}
return result;
}
private static int[][] del(int[][] a, int[][] b, int n) {
int[][] result = new int[n][n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
result[i][j] = a[i][j] - b[i][j];
}
}
return result;
}
}
关于分治算法的个人理解