资讯详情

6010. 完成旅途的最少时间,二分查找的好(ěxīn)题

6010. 至少完成旅程

282场周赛的第三个问题,比赛没有做出来,提交基本上是加班,最后半小时想用两分找到,但很多无法解释bug,下午看了别人的问题,自己做了很多。bug,第16次提交终于通过了,所以记录下遇到的坑。

需注意的点

1.在搜索开始时确定最大值和最小值

我的想法是:

假设每辆车的单次旅行时间最少,得到最小值:最小时间=旅途总数*单次旅行的最小时间/车辆数量;同理,最大时间=旅途总数*单次旅行的最大时间/车辆数量

有一个非常严重的问题:int型除法只保留整数,会造成很大的误差!

(例如:最大时间=199(次旅途)*(最大单程)/100(车辆)=3(分钟)。然而,100辆车在3分钟内跑不完199趟)。

虽然我想到了这一点,但我采用的方法是尝试int转换为double,这样改变巨大的麻烦也容易出错~

下午才想到办法,整数除法的误差只会使结果变小,这只会对最大值产生重要影响,并增加可能的范围,这里有两种加法:

  • 最大时间=旅行总数/车数*单次旅行的最大时间 这样,可能会有一些旅程小于汽车的数量(也就是说,剩下的旅程不需要所有的汽车出去再跑)。这部分被遗弃了,但事实上,一些汽车必须被转移,也就是说,最大时间=(旅行总数/车数 1)*单次旅行的最大时间。
  • 最大时间=旅途总数*单次旅行的最大时间/车辆数量 这样,可能会有一部分时间值小于汽车数量的值(也就是说,剩下的时间不足以让所有的汽车一起再走一分钟),并被遗弃。但事实上,剩下的时间仍然需要完成,也就是说,仍然需要派一些汽车,一旦派出的汽车被派出,就必须完全完成一次旅行。因此,原始公式改为最大时间=旅途总数*单次旅行的最大时间/车辆数量 单次旅行的最大时间。

若要使用带整数除法的解法,必须理解误差的含义,然后再考虑如何弥补,从数学的角度来看,不要认为小数在整数除法后被放弃,小数必须小于1,所以直接在任何除法结束后 1.例如,如果将上述情况2改为最大时间=旅途总数*单次旅行的最大时间/车辆数量 1,这似乎超过了放弃的小部分,但从意义上看,所有的车都可能出去,但只有一分钟?今天在这个小地方卡了很久,说白了就是懒得想的锅。

想不通就好尽量避免整数除法,看了别人的题解,采取了:最小时间=单次旅行的最小时间;假设只有一辆车,那么最大时间=旅途总数*单次旅行的最小时间。确实可以确定范围,避免整形除法(但只有乘法会超过)int必须将范围转换为long long)。

既然只是确定范围,就不用在一个想法上敲门了。如果卡住了,想想有没有更好的理解,更不用说误差了。

2.在搜索过程中max和min的值变化

常规二分搜索是当取mid假如结果>目标时使max=mid-1;结果<目标时,min=mid 1,结果==目标时返回mid。

但这个问题有点不同:

  • 取mid假如结果>目标可能是因为在这一分钟内到达目的地的汽车太多,导致结果从最后一分钟小于目标转变为超过目标。换句话说,虽然结果大于目标,但mid可能就是要找的答案,因此,本题中计算结果>目标时,令max=mid。
  • 如果结果==目标可能是因为这一分钟内没有车到达目的地,也许前一分钟是最终答案。因此,这个问题不能计算结果==目标时return mid,继续搜索,知道最终范围内只剩下一个值。

3.结束搜索出口

循环出口纠结了很久。min<max还是min<=max,下次遇到记得这样考虑:

  1. 可以用2~四个模拟,看最后会不会出现。min>max这种情况不会发生在这个问题上。while(min<=max),将进入无限循环。
  2. 考虑如果用min<max,是否会有元素被忽略,例如,如果返回是bool类型,只在循环中搜索,必须使用min<=max,或者单独判断只有一个元素,这个问题不太可能只有一个元素,但即使只有一个元素,也是这个元素(而不是bool类型),所以不需要,=。

其他细节

1.可以用max_element(s.begin(),s.end) ,min_element(s.begin(),s.end) 返回最大最小值对应的迭代器(带*调用哦),这样比较sort(),再取头尾,效率明显提高。

auto most =max_element(time.begin(), time.end()); auto least =min_element(time.begin(), time.end());

代码

class Solution { public:     long long minimumTime(vector<int>& time, int totalTrips) {         long long total;         auto most =max_element(time.begin(), time.end());         auto least =min_element(time.begin(), time.end());         long long max=(long long)((long long)totalTrips* (*most)/time.size() time[time.size()-1]);         long long min=(long long)(totalTrips/time.size())*(*least);         long long mid=(min max)/2;          while(min<max){             total=0;             for(int j:time){                 total =mid/j;               }             if(total>=totalTrips){                 max=mid;             }             else if(total<totalTrips){                 min=mid 1;             }             mid=(min max)/2;         }return mid;     }      };

标签: eaco电容900v600uf

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台