【LeetCode - 每日一题】2594. 修车的最少时间(23.09.07)

2594. 修车的最少时间

题意

  • 给定每个师傅修车的时间和需要修的车辆总数,计算修理所有汽车需要的最少时间。
  • 师傅可以同时修车。

解法 二分

看到题目没有任何头绪,直接查看题解。

至于为什么用二分做呢,讨论区有个友友这么说到:

对于修理时间 t t t 来说:

  • 若 t t t 时间内可以修理完所有车,则大于等于 t t t 时间都可以修理完车;
  • 若 t t t时间内不能修理完所有车,则小于等于 t t t 时间也不能修理完车;

存在单调性。因此,假设最少需要 t i m e time time 时间,那么我们要找的就是第一个大于等于 t i m e time time 的时间 t t t 。

所以可以直接套板子:

cpp 复制代码
class Solution {
public:
    long long repairCars(vector<int>& ranks, int cars) {
        long long maxTime = (long long)*max_element(ranks.begin(), ranks.end()) * cars * cars;

        long long left = 0, right = maxTime, middle;
        
        long long maxCar = 0;
        while(left < right)
        {
            long long middle = (left +right) / 2;
            maxCar = 0;
            for(auto rank :ranks)
            {
                maxCar += sqrt(middle / rank);  
            }
            // cout << left << " " << right << " " << middle << " " << maxCar << endl;
            
            if(maxCar < cars)
            {
                left = middle + 1;
            }
            else if(maxCar >= cars)
            {

                right = middle;
            }
        }
        return left;
    }
};

另一种写法:

cpp 复制代码
class Solution {
public:
    long long repairCars(vector<int>& ranks, int cars) {
        long long maxTime = (long long)*max_element(ranks.begin(), ranks.end()) * cars * cars;

        long long left = 0, right = maxTime, middle;
        
        long long maxCar = 0;
        while(left <= right)
        {
            long long middle = (left +right) / 2;
            maxCar = 0;
            for(auto rank :ranks)
            {
                maxCar += sqrt(middle / rank);  
            }
            // cout << left << " " << right << " " << middle << " " << maxCar << endl;
            
            if(maxCar < cars)
            {
                left = middle + 1;
            }
            else if(maxCar > cars)
            {

                right = middle - 1;
            }
            else if(maxCar == cars)
            {
                right = middle - 1;
            }
        }
        return left;
    }
};

板子:

cpp 复制代码
int lower_bound(int a[],int left,int right,int x) 	//第一个小于等于x的数的位置 
{
	int mid;
	while(left<right)
	{
		mid=(left+right)/2;
		if(a[mid]>=x)
			right=mid;
		else
			left=mid+1;
	}
	return left;
}

int lower_bound(int a[],int left,int right,int x) 	//第一个小于等于x的数的位置 
{
	int mid;
	while(left<=right)
	{
		mid=(left+right)/2;
		if(a[mid]>=x)
			right=mid-1;
		else
			left=mid+1;
	}
	return left;
}

复杂度

时间复杂度:O( r a n k s . s i z e ( ) ∗ ( log ⁡ m a x ( r a n k ∗ c a r s ∗ c a r s ) ) ranks.size() * (\log max(rank*cars*cars)) ranks.size()∗(logmax(rank∗cars∗cars)) ),每一次二分都要遍历 ranks 数组计算可修理最大车辆数。

空间复杂度:O(1),常数个变量。


相关推荐
小冯记录编程4 分钟前
C++指针陷阱:高效背后的致命危险
开发语言·c++·visual studio
C_Liu_1 小时前
C++:类和对象(下)
开发语言·c++
coderxiaohan1 小时前
【C++】类和对象1
java·开发语言·c++
阿昭L1 小时前
MFC仿真
c++·mfc
老赵的博客3 小时前
c++ unqiue指针
java·jvm·c++
程序猿编码4 小时前
基于 Linux 内核模块的字符设备 FIFO 驱动设计与实现解析(C/C++代码实现)
linux·c语言·c++·内核模块·fifo·字符设备
怎么没有名字注册了啊4 小时前
MFC_Install_Create
c++·mfc
Wadli5 小时前
C++语法 | static静态|单例模式
开发语言·c++·单例模式
_不会dp不改名_6 小时前
leetcode_21 合并两个有序链表
算法·leetcode·链表
进击的_鹏6 小时前
【C++11】initializer_list列表初始化、右值引用和移动语义、可变参数模版等
开发语言·c++