查看: 2253| 回复: 12
跳转到指定楼层
上一主题 下一主题
收起左侧

[二分/排序/搜索] first badversion用左闭右开区间有没有简洁的写法?

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 gavinwWELL 于 2020-6-6 05:34 编辑

习惯了左闭右开区间模板,怎么用在这道题目上比起左闭右闭的写法要复杂?(终止条件后需要检查两个可能的位置)难道左闭右闭的写法有先天的优势?(终止条件后只需要检查一个可能的位置)能不能用左闭右开的写法并且终止条件后只需要检查一个可能的位置?

// 左闭右闭
  1.     public int firstBadVersion(int n) {
  2.         int l=1,r=n;
  3.         while(l<r){ // 终止条件后只需要检查一个可能的位置: l
  4.             int mid=l+(r-l)/2;
  5.             if(isBadVersion(mid)) r=mid;
  6.             else l=mid+1;
  7.         }
  8.         
  9.         if(l>r) return -1;
  10.         else return isBadVersion(l)?l:-1;
  11.     }
复制代码




//左闭右开
  1.   public int firstBadVersion(int n) {
  2.         if(n<2) return 1;
  3.         int b=1,e=n+1;
  4.         while(b<e-2){ // 终止条件后需要检查两个可能的位置: b, b+1
  5.             int mid=b+(e-b)/2;            
  6.             if(isBadVersion(mid-1) e=mid // 而且为什么必须用mid-1的值?
  7.             else b=mid;
  8.         }

  9.         return isBadVersion(b)? b: b+1; //终止条件后需要检查两个可能的位置

  10.     }
  11.         
  12.     }
复制代码












补充内容 (2020-6-6 06:40):

loop invariant: 解存在于区间窗口中

上一篇:算法课程对转行的小白的效益大吗?
下一篇:2020.6.5刷题
推荐
ctzsm 2020-6-8 03:12:09 | 只看该作者
全局:
2楼的写法是对的,我一直就这么写。我最近线段树也改成了左闭右开。

整个C++ STL的思想都是左闭右开,可以看看STL的源码。binary search看lower_bound()和upper_bound()的实现。https://en.cppreference.com/w/cpp/algorithm/lower_bound
回复

使用道具 举报

推荐
hoooga 2020-6-8 02:24:35 | 只看该作者
全局:
gavinwWELL 发表于 2020-6-7 08:23
现学现用套用了几道题,这个技巧还挺好用的,请问有没有介绍类似技巧的书籍?谢谢

一些竞赛书里应该会有
回复

使用道具 举报

推荐
hoooga 2020-6-6 06:53:41 | 只看该作者
全局:
gavinwWELL 发表于 2020-6-5 14:37
用这个loop invariant倒是解释得通了。

很巧妙,不过直观程度上能想出来也是不容易,厉害

我一般把binary search问题抽象成这样:已知存在一个函数f,在区间[begin, mid)函数值为True,在[mid, end)函数值为False,然后用bs求解mid。比如在First Bad Version这里,f就是isBadVersion。我的经验是,在别的binary search题目里,也可以这样formulate问题,求解也会比较轻松。

评分

参与人数 2大米 +2 收起 理由
Dustinlo + 1 给你点个赞!
gavinwWELL + 1 很有用的信息!

查看全部评分

回复

使用道具 举报

🔗
hoooga 2020-6-6 06:27:00 | 只看该作者
全局:
本帖最后由 hoooga 于 2020-6-5 14:33 编辑

左闭右开:

  1. class Solution {
  2. public:
  3.     int firstBadVersion(int n) {
  4.         long long begin = 1;
  5.         long long end = (long long)n + 1;
  6.         while (begin < end) {
  7.             long long mid = begin + (end - begin)/2;
  8.             if (isBadVersion(mid)) {
  9.                 end = mid;
  10.             } else {
  11.                 begin = mid + 1;
  12.             }
  13.         }
  14.         return begin;
  15.     }
  16. };
复制代码

整个算法过程中不变的性质:(-inf, begin) 区间都是good version, [end, +inf) 区间都是bad version, [begin, end)未知。跳出loop后,begin和end重合,由前述性质可知,begin是第一个bad version。

评分

参与人数 1大米 +1 收起 理由
gavinwWELL + 1 很有用的信息!

查看全部评分

回复

使用道具 举报

🔗
 楼主| gavinwWELL 2020-6-6 06:33:10 | 只看该作者
全局:
本帖最后由 gavinwWELL 于 2020-6-6 06:34 编辑


运行通过, it just works, 但是无法理解:
  1. if (isBadVersion(mid)) {
  2.                 end = mid;
  3.             }
复制代码


请解释一下,如果mid是bad version, , 那么mid也可能是解,但是把end设成mid岂不是把它排除在外了吗?
要知道左闭右开 [begin, end) 里面的end是不包括在区间里面的
回复

使用道具 举报

🔗
hoooga 2020-6-6 06:35:30 | 只看该作者
全局:
我原回复后面增加了解释
回复

使用道具 举报

🔗
 楼主| gavinwWELL 2020-6-6 06:37:47 | 只看该作者
全局:
hoooga 发表于 2020-6-6 06:27
左闭右开:

[mw_shl_code=bash,true]class Solution {

用这个loop invariant倒是解释得通了。

很巧妙,不过直观程度上能想出来也是不容易,厉害
回复

使用道具 举报

🔗
 楼主| gavinwWELL 2020-6-6 06:39:51 | 只看该作者
全局:
loop invariant: 解存在于区间窗口中
回复

使用道具 举报

🔗
ovarer 2020-6-6 07:20:48 | 只看该作者
全局:
本帖最后由 ovarer 于 2020-6-6 07:31 编辑
gavinwWELL 发表于 2020-6-6 06:33
运行通过, it just works, 但是无法理解:
[mw_shl_code=java,true]if (isBadVersion(mid)) {
      ...

是的,所以写成 end = mid + 1 应该也行
edit:
哦不不行,会死循环……binary search真烧脑
这边如果 mid 是解,loop exit 的时候 low 就会是 mid,return low return 的就是解
回复

使用道具 举报

🔗
 楼主| gavinwWELL 2020-6-8 00:23:56 | 只看该作者
全局:
hoooga 发表于 2020-6-6 06:27
左闭右开:

[mw_shl_code=bash,true]class Solution {

现学现用套用了几道题,这个技巧还挺好用的,请问有没有介绍类似技巧的书籍?谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表