蓝桥杯刷题6--二分法

本文介绍了二分法的基本概念及其在不同编程问题中的应用,如排序后进行二分查找、计算阶乘的近似值、分巧克力和跳石头游戏中的最小值最大化策略,以及青蛙过河问题的解决方案。通过实例展示了如何在有序序列中高效利用二分法优化搜索过程。
摘要由CSDN通过智能技术生成

1. 二分法

注意二分法的应用条件是:序列是单调有序的,从小到大,或从大到小。在无序的序列上无法二分,如果是乱序的,应该先排序再二分。

1.1 代码实现

import java.util.*;
class Main {
    static int[] a = new int[105];
    static boolean check(int x, int mid) { return x <= a[mid]; }
    static int bin_search(int n, int x) {
        int L = 1;
        int R = n;
        while (L < R) {
            int mid = (L + R) / 2;
            if (check(x, mid))     R = mid;
            else                   L = mid + 1;            
        }
        return a[L];
    }

    public static void main(String[] args) {
        int n = 100;
        for (int i = 1; i <= n; i++)   a[i] = i;        
        int x = 68;
        System.out.println("x=" + bin_search(n, x));
    }
}

2. 习题

2.1 求阶乘

import java.util.*;

public class Main {
  public static long check(long mid){
      long count = 0;
      while(mid > 0){
        count += mid/5;
        mid /= 5;
      }
      return count;
    }
  public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        long k = scan.nextLong();
        long left = 0;
        long right = (long) Math.pow(10,19);
        while(left < right){
          long mid = (left + right)/2;
          if(check(mid) >= k) right = mid;
          else left = mid + 1;
        }
        if(check(right)==k) System.out.println(right);
        else System.out.println(-1);
        scan.close();
    }
}

2.2 分巧克力

import java.util.*;
public class Main {
    static int k,n;
    static final int max = 100010;
    static int h[] = new int[max];
    static int w[] = new int[max];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        k = scan.nextInt();
        for(int i = 0;i<n;i++){
          h[i] = scan.nextInt();
          w[i] = scan.nextInt();
        }
        int L = 1;
        int R = max;
        while(L<R){
          int mid = (L + R + 1) >> 1;
          if(check(mid)) L = mid;
          else R = mid-1;
        }
        System.out.println(L);
        scan.close();
    }

    public static boolean check(int d){
      int count = 0;
      for(int i = 0;i<n;i++){
        count += (h[i]/d) * (w[i]/d);
      }
      if(count >= k) return true;
      else return false;
    }
}

2.3 最小值最大化:跳石头

import java.util.Scanner;
public class Main {
    static int len, n, m;
    static int[] stone;
    static boolean check(int d) {
        int num = 0; // num记录搬走石头的数量
        int pos = 0; // 当前站立的石头
        for (int i = 1; i <= n; ++i)
            if (stone[i] - pos < d)         num++; // 可以搬走
            else                pos = stone[i]; // 不能搬走
        if (num <= m)       return true; 
        else            return false; 
    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        len = scan.nextInt();
        n = scan.nextInt();
        m = scan.nextInt();
        stone = new int[n + 1];
        for (int i = 1; i <= n; i++){
          stone[i] = scan.nextInt();
        }
       int L = 0;
       int R = len;
        while (L < R) {
            int mid = L + (R - L) / 2;
            if (check(mid))  L = mid + 1; // 说明mid小了,调大一点
            else             R = mid - 1; // 说明mid大了,调小一点
        }
        if (!check(R))  R += 1;
        System.out.println(R);
        scan.close();
    }
}

2.4 青蛙过河

import java.util.*;
public class Main{

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n =scan.nextInt();
        int x = scan.nextInt();
        long[] arr = new long[n+1];//存放每一个石头的位置
        for(int i=1;i<n;i++) { // * 0,1,1,2,2,inf
            arr[i] = scan.nextLong()+arr[i-1];
        }
        arr[n] = arr[n-1]+1<<10;//对岸设置为无穷大
        int l=0;
        int r = n;
        while(l<r) {
            int mid = (l+r)/2;
            if(check(mid,arr,n,x)) {
                r = mid;
            }else {
                l = mid+1;
            }
        }
        System.out.println(l);
        
    }
    public static boolean check(int k,long[] arr,int n,int x) {
        for(int i=0;i<n-k;i++) {//任意k个大小的区间大于等于2*x
            if(arr[i+k]-arr[i] <2*x)
                return false;
        }
        return true;
    }

}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值