蓝桥杯--分治法与动态规划(一)

例1【二分查找】

已知有序的序列 int[] a,
整数 x,要求找到一个刚好比x稍微大一点的元素位置
public class Main {
    //区间左闭右开
    static int f(int []a,int low,int high,int x){
       if(high-low==1){
           if(a[low]>x)
               return low;
           return high;
       }
       int mid = (low + high) / 2;
       if(x<a[mid])
           return f(a,low,mid,x);
       else
           return f(a,mid,high,x);
    }

    //求x应该插入的位置
    //return 刚好比x稍微大点的那个数的位置
    static int f(int []a,int x){
        if(x>=a[a.length-1])//不存在比x稍大的数字
            return -1;
        return f(a,0,a.length,x);
    }

    public static void main(String[] args) {
        int []a={1,5,11,24,25,32,32,33,49,66,68,69,70,75,88,102,114,119,120,135,146,221,294,300,302,305,333};
        System.out.println(f(a,32));

    }
}

例2【最大连续部分和】 

数组中整数有正有负
求连续一子段,使得和最大化
2,4,-7,5,2,-1,2,-4,3
最大连续段:5,2,-1,2
最大和为8

思路分析:利用分治思想,分成三个部分,前一半和后一半的最大连续和,以及中间往两边的最大值

public class Main {
    //区间左闭右开
    static int f(int []a,int low,int high){
        if(high-low==1){
            if(a[low]>0)//若a[low]<0 ,可以不取值
                return a[low];
            return 0;
        }

        int mid = (low + high)/2;
        int left = f(a,low,mid);//左半部分寻找最大连续部分和
        int right = f(a,mid,high);//右半部分寻找最大连续部分和
        int mid1 = 0;
        int sum = 0;
        for(int i=mid-1;i>=low;i--){
            sum = sum + a[i];
            if(sum>mid1) mid1=sum;
        }
        int mid2 = 0;
        sum = 0;
        for(int i=mid;i<high;i++){
            sum = sum + a[i];
            if(sum>mid2)
                mid2 = sum;
        }
        int max = mid1 + mid2;//中间向两边扩展的最大连续部分和
        if(max<left)
            max = left;
        if(max<right)
            max = right;
        return max;
    }

    public static void main(String[] args) {
        int[]a= {2,4,-7,5,2,-1,2,-4,3};
        System.out.println(f(a,0,a.length));//8
    }
}

例3【大数乘法】

multi("5935849584045839123456789","4595805849258430535")
public class Main {
    static String add(String a,String b){//大数相加
        if(a.length()<=8 && b.length()<=8)
            return Integer.parseInt(a) + Integer.parseInt(b) + "";
        String a1 = "0";
        String a2 = a;
        if(a.length()>8){//将a的低8位分离出
            a1 = a.substring(0,a.length()-8);
            a2 = a.substring(a.length()-8);
        }
        String b1 = "0";
        String b2 = b;
        if(b.length()>8){//将a的低8位分离出
            b1 = b.substring(0,b.length()-8);
            b2 = b.substring(b.length()-8);
        }
        String t = add(a2,b2);
        if(t.length()>8)
            return add(add(a1,b1),"1") + t.substring(1);
        if(t.length()<8){
            return add(a1,b1) + zero(8-t.length())+ t;
        }
        return add(a1,b1) + t;
    }

    static String zero(int x){
        if(x==0) return "";
        if(x==1) return "0";
        return zero(x/2) + zero(x/2) + zero(x%2);
    }

    static String multi(String a,String b){//大数相乘
        if(a.length()<=4 && b.length()<=4)
            return Integer.parseInt(a) * Integer.parseInt(b) + "";
        if(a.length()>4){
            int mid = a.length()/2;
            String s1 = a.substring(0,mid);
            String s2 = a.substring(mid);
            return add(multi(s1,b) + zero(s2.length()),multi(s2,b));
        }
        return multi(b,a);
    }

    public static void main(String[] args) {
        System.out.println(multi("12345678900987654321666","1234567890123456789555"));
        System.out.println(new BigInteger("12345678900987654321666").multiply(new BigInteger("1234567890123456789555")));//验证
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值