分治算法

分治算法是一种有效的解决问题的方法,适用于规模缩小后容易解决、具有最优子结构及子问题相互独立的问题。常见的分治算法应用包括二分查找、快速排序和合并排序等。了解分治法的关键在于理解其在递归过程中的三个步骤,并通过实践来掌握这种算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分治法所能解决的问题一般具有以下几个特征:
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;
第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、
第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

分治法在每一层递归上都有三个步骤:

step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题

step3 合并:将各个子问题的解合并为原问题的解。

看了那么多生硬的文字,没啥感觉还是老一套,做题!
一、寻找假币

public class FalseCoin {
    public static void main(String[] args) {
        int arr[]={2,2,2,2,2,1,2,2};
        int x=method(arr,0,arr.length-1);
        if(x==-1){
            System.out.println("没有假币");
        }else{
            System.out.println("第"+(x+1)+"个金币是假币!");
        }

    }

    private static int method(int[] arr, int l, int r) {
        int re,sum1=0,sum2=0,mid;

        if(l==r){               //筛选到最后一个币时
            if(arr[l]==2){
                return -1;
            }else{
                return l;
            }
        }
        //筛选到只有两个金币时
        if(l+1==r){
            if(arr[l]<arr[r]){
                re=l;
                return re;
            }else if(arr[l]>arr[r]){
                re=r;
                return re;
            }else{
                return -1;
            }
        }
        //金币数是偶数
        if((r-l+1)%2==0){
            for(int i=l;i<=l+(r-l)/2;i++){      //前半段 求和
                sum1=sum1+arr[i];
            }
            for(int i=l+(r-l)/2+1;i<=r;i++){    //后半段 求和
                sum2=sum2+arr[i];
            }
            if(sum1>sum2){
                re=method(arr,l+(r-l)/2+1,r);
                return re;
            }else if(sum1<sum2){
                re=method(arr,l,l+(r-l)/2);
                return re;
            }else{
                return re=-1;//sum1=sum2没有假币,返回负数
            }
        }
        //金币数是奇数时
        else{
            for(int i=l;i<=l+(r-l)/2-1;i++){        //前半段 求和
                sum1=sum1+arr[i];
            }
            for(int i=l+(r-l)/2+1;i<=r;i++){        //后半段 求和
                sum2=sum2+arr[i];
            }

            mid=l+(r-l)/2;

            if(sum1>sum2){
                re=method(arr,l+(r-l)/2+1,r);
                return re;
            }else if(sum1<sum2){
                re=method(arr,l,l+(r-l)/2-1);
                return re;
            }else{
                re=method(arr,mid,mid);
                return re;
            }
        }
    }
}

二、二分查找

public class BinarySearch {


    public static int search(int target, int[] data,int min, int max) {
        if (min > max) {
            return -1;
        }

        int n = (min + max) / 2;

        if (target > data[n]) {
            min = n + 1;
        }

        if (target < data[n]) {
            max = n - 1;
        }

        if (target == data[n]) {
            return n;
        } else {
            return search(target,data, min, max);
        }
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 7, 9, 25, 44, 66, 99 };
        System.out.println(search(50, arr,0, arr.length - 1));
        System.out.println(search(66, arr,0, arr.length - 1));
    }
}

三、快速排序
http://blog.youkuaiyun.com/java_zero2one/article/details/51567506

四、合并排序
http://blog.youkuaiyun.com/java_zero2one/article/details/51658467

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值