算法之分治算法

所谓分治算法,就是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。

概念:
求解某些问题时,由于问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。

基本思路:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

例题分析:
给你一个装有4个硬币的袋子(4 个硬币的重量均不一样)。将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,找到最重的那枚硬币。
(题目可以看成给出4个数,然后求其中的最大值)
相信很多人题目看完就知道该怎么做了,不过或许和你想的不一样。

解题过程:
首先将4个硬币分为2份进行比较,2组都不可再分,这样比较就会出现2个在本组中最重的硬币,然后2个相比较,直接得到最重的硬币。

过程不难,就像一个倒的二叉树,将问题分解为和原问题相同的子问题,再对子问题进行解决。从而求解。(原问题是求4个中的最大值,而子问题是求2个中的最大值,得到答案只比较了3次)

下面给出一个实例,并用代码进行解题:
在n个元素中找出最大元素和最小元素。(就是这么简单的题,不过用的是上面所讲的思想)

解题步骤:
求n个元素中找出最大值和最小值==求2组 n/2个元素中找出最大值和最小值==在4组 n/4个元素中找出最大值和最小值…………
一直到最后的,直接比较n组2个数的大小,大的即为本组中的最大值,小的即为本组中的最小值(如果本组中只有一个数,那么这个数即为最大值,也为最小值)
得到的最大值最小值返回父集,那么父集中也只会存在2组最大值与最小值,再将比较过后的值返回给父集的父集…………最后得到答案。

接下来我们来看代码:

package 分治算法;
import java.util.Scanner;
class IntPair{
    int max;//存放最大值
    int min;//存放最小值
}
public class 求最大最小值 {
    /** * 在n个元素中找出最大元素和最小元素。 * @param args */ 
    public static void main(String[] args){
        System.out.print("请输入元素的个数:");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        System.out.print("请输入元素的值:");
        int arr[] = new int[num];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = scanner.nextInt();
        }
        IntPair pair = min_max(arr, 0, num-1);  
        System.out.print("最大值为:" + pair.x + " ");  
        System.out.print("最小值为:" + pair.y);  
    }
    //第一个参数:需要求值的数组,第二个参数:所分组的起始下标,第三个参数:所分组的结束下标
    public static IntPair min_max(int[] arr, int low, int high){ 
       IntPair pair = new IntPair();
       //判断本组元素是否不可分
       if (low > high - 2){     
           //将本组中的最大值与最小值存入pair 
           if (arr[low] < arr[high]){    
               pair.max = arr[high];
               pair.min = arr[low]; 
           }else{   
               pair.min = arr[high];
               pair.max = arr[low]; 
           } 
       }else{    
           //如果本组可分
           int mid = (low + high)/2;   
           //则分别得到2组的最大值最小值
           IntPair p1 = min_max(arr, low, mid);   
           IntPair p2 = min_max(arr, mid+1, high);
           //将不可分子集返回的数据进行比较 
           pair.max = p1.max > p2.max ? p1.max : p2.max;   
           pair.min = p1.min < p2.min ? p1.min : p2.min;    
       }    
       return pair;   
    }
}

担心各位看代码也不是很明白,我这里再啰嗦2句。
就好比求1,3,2,5,4,6,9这7个数据中的最大值
第一步:分为[1,3,2,5]与[4,6,9]两组
第二歩:将[1,3,2,5]分为[1,3]与[2,5]两组
然后2组数据均不可再分,比较后得到2个最大值,3与5
第三步:将[4,6,9]分为[4,6]与[9]两组
与上同理,得到6与9
第四步:[1,3,2,5]变成[3,5],[4,6,9]变为[6,9]
与上同理,得到5与9
第五步:[1,3,2,5,4,6,9]变为[5,9]
与上同理,得到最后的最大值为9。

希望大家有所收获,也希望大家能提出自己独到的见解。

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/zyh2525246/article/details/79572164
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞