算法(二分查找C++

文章讲述了如何通过二分查找法在有序整数数组中找到目标值的开始和结束位置,以及如何计算将原木切割成等长小段的最大长度,同时提出了时间复杂度优化的要求。
摘要由CSDN通过智能技术生成

有一点点难受这个算法,俩个题目给我的感觉代码都差不多但是意思大相径庭,我暂时没有很好的解释,先把他放在这里,看看我之后能不能很好的解释:

第一题

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:你可以设计并实现时间复杂度为 $O(\log n)$ 的算法解决此问题吗?

示例 1:

  • 输入:nums = [5,7,7,8,8,10], target = 8
  • 输出:[3,4]

示例 2:

  • 输入:nums = [5,7,7,8,8,10], target = 6
  • 输出:[-1,-1]

示例 3:

  • 输入:nums = [], target = 0
  • 输出:[-1,-1]

代码: 

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left=Left(nums,target);
        int right=Right(nums,target);
        if(left==-2||right==-2){
            return {-1,-1};
        }
        if (right-left>1){
            return {left + 1, right - 1};
        }
        return {-1, -1};
    }
private:
    int Left(vector<int>& nums, int target){
        int left=0;
        int right=nums.size()-1;
        int flag=-2;
        while(left<=right){
            int middle=left+(right-left)/2;
            if(nums[middle]>=target){
                right=middle-1;
                flag=right;
            }else{
                left=middle+1;
            }
        }
        return flag;
    }
    int Right(vector<int>& nums, int target){
        int left=0;
        int right=nums.size()-1;
        int flag=-2;
        while(left<=right){
            int middle=left+(right-left)/2;
            if(nums[middle]>target){
                right=middle-1;
            }else{
                left=middle+1;
                flag=left;
            }
        }
        return flag;
    }
};

第二题

题目描述

木材厂有 n 根原木,现在想把这些木头切割成 k 段长度均为 l 的小段木头(木头有可能有剩余)。

当然,我们希望得到的小段木头越长越好,请求出 l 的最大值。

木头长度的单位是 cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为 11 和 21,要求切割成等长的 6 段,很明显能切割出来的小段木头长度最长为 5

输入格式

第一行是两个正整数 n,k,分别表示原木的数量,需要得到的小段的数量。

接下来 n 行,每行一个正整数 Li,表示一根原木的长度。

输出格式

仅一行,即 l 的最大值。

代码:

#include <iostream>
#include <cstring>
using namespace std;
int check(int middle,int weight[],int n);
int main(){
    int n,k;
    cin>>n>>k;
    int weight[n];
    int sum=0;
    int max1=0;
    for(int i=0;i<n;i++){
        cin>>weight[i];
        sum+=weight[i];
        max1=max(max1,weight[i]);
    }
    int left=1;
    int right=max1;
    while(left<=right){
        int middle=left+(right-left)/2;
        if(check(middle,weight,n)>=k){
            left=middle+1;
        }else{
            right=middle-1;
        }
    }
    if(sum<k){
        cout<<0;
    }else{
        cout<<right;
    }
    return 0;
}
int check(int middle,int weight[],int n){
    int sum = 0;
	for(int i = 0;i < n;i++) {
		sum+=weight[i]/middle;
	}
	return sum;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值