二分学习

思路

首先需要确定能否使用二分。对于二分问题而言,二分答案需要保持单调性,但数组并不一定需要保持单调性。

第二步确定问题需要定位的位置,例如寻找第一个大于等于target的位置或最后一个大于等于target的位置。

第三步确定左右边界。

在排序数组中查找元素的第一个和最后一个位置

  • 对于本题而言,数组单调可以使用二分查找
  • 需要查找的是第一个大于等于target的位置
  • 我常使用的是左闭右开,所以下面的答案都使用的是左闭右开模版。左边界明显为0,右边界为数组长度n。
func searchRange(nums []int, target int) []int {


    var s1 func(target int)int

    s1 = func(target int)int{
       l,r := 0,len(nums) //定义左右边界
    for l < r{  //确定终止位置
        mid := l+(r-l)/2 //防止溢出
        if nums[mid] >= target{ //找到第一个大于等于的位置
            r = mid
        }else{
            l = mid+1
        }
    }
    return r
    }

    start := s1(target)

    if start == len(nums) || nums[start] != target{
        return []int{-1,-1}
    }
    end := s1(target+1)-1
    return []int{start,end}
}

2300. 咒语和药水的成功对数

思路

  • 对于potions而言,显然越大越容易成立,越小越不成立。具有二分性质

  • 本题也可以找到第一个大于等于target的位置,再用potions长度减去即可获得后方的长度

  • 左边界为0,右边界为数组长度。

func successfulPairs(spells []int, potions []int, success int64) []int {

    sort.Ints(potions)

    for i,x := range spells{
        l,r := 0,len(potions)

        for l < r{
            m := l+(r-l)/2

            if int64(x*potions[m]) >= success{
                r = m
            }else{
                l = m+1
            }
        }
        spells[i] = len(potions)-l
    }
    return spells



    return spells
}

2563. 统计公平数对的数目

思路

  • 这题显然具有单调性,可以使用二分

  • 这题可以分为两个部分,第一部分找到第一个大于等于lower的位置,第二部分是找到最后一个小于等于upper的位置,第二部分也可以转换成第一个大于等于upper+1的位置

  • 左边界显然继续为0,右边界为数组长度

func countFairPairs(nums []int, lower int, upper int) (res int64) {
    sort.Ints(nums)

    var s1 func(n []int,target int) int

    s1 = func(n []int,target int) int {
        l, r := 0, len(n)
        for l < r {
            mid := l + (r-l)/2
            if n[mid] >= target {
                r = mid
            } else {
                l = mid + 1
            }
        }
        return r
    }
    fmt.Println(nums)
    for i := 0; i < len(nums); i++ {
        p,q := s1(nums[i+1:],upper-nums[i]+1),s1(nums[i+1:],lower-nums[i]) //数组会不断变小
   
        res += int64(p-q)
    }
    return 
}

875. 爱吃香蕉的珂珂

思路

  • 对于最小速度k而言,明显具有单调性。大的能成,小的不一定能成

  • 这题需要找到第一个大于等于target的位置

  • 左边界为1,右边界为piles中的最大值。

func minEatingSpeed(piles []int, h int) int {
    l,r := 1,slices.Max(piles)

    for l < r{
        m := l+(r-l)/2
        cnt := 0
        for _,x := range piles{
            cnt += (x+m-1)/m
        }

        if cnt > h{ //大于边界时l 往左边移动,反之往右
            l = m+1
        }else{
            r = m
        }
    }
    return l
}

2187. 完成旅途的最少时间

思路

  • 同上,答案具有单调性

  • 需要找到第一个大于等于target的位置

  • 左边界为排列后的最快速度,右边界为最快速乘以趟数

func minimumTime(time []int, totalTrips int) int64 {
    sort.Ints(time)
    l,r := time[0], totalTrips*time[0]

    for l < r{
        m := l+(r-l)/2
        cnt := 0
        for _,x := range time{
            cnt += m/x
        }

        if cnt >= totalTrips{
            r = m
        }else{
            l = m+1
        }
    }
    return int64(l)
}

2861. 最大合金数

思路

  • 单调性同上

  • 需要找到第一个大于等于的位置,若check满足则左边界变为mid+1,不满足则右边界为mid

  • 左边界为0,右边界为budget+1

func maxNumberOfAlloys(n int, k int, budget int, composition [][]int, stock []int, cost []int) int {
    check := func (target int) bool { // target 是我们想要制造的合金数量
        for _, machine_i := range composition { // 选择使用第 i 台机器
            remain := budget // 预算
            for i, v := range machine_i { // v 是制造该合金需要该类金属的数量
                need := max(0, v*target-stock[i]) // 需要购买 i 类金属的数量, (该数不能小于 0)
                remain -= need*cost[i] // 买这些金属需要花的钱
            }
            if remain >= 0 {
                return true
            }
        }
        return false
    }

    l, r := 0, int(2e8)+1 // 题目很坑, 说好的数据范围到 1e8, 结果给到 2e8
    for l < r {
        mid := l+(r-l)>>1
        if check(mid) { // mid 作为想要制造和合金数, 如果符合, 就让 l = mid, l 即为答案
            l = mid+1
        } else {
            r = mid
        }
    }
    return l-1
}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 一、介绍 二分查找的前提 目标函数单调性(单调递增或递减) 存在上下界(bounded) 能够通过索引访问(ind...
    alex很累阅读 143评论 0 0
  • 点赞关注,不再迷路,你的支持对我意义重大!Hi,我是丑丑。本文「数据结构 & 算法」| 导读 —— 登高博见[ht...
    彭旭锐阅读 1,670评论 1 6
  • 有序矩阵中第K小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。请注意...
    我是小曼巴阅读 1,679评论 0 1
  • 前言 二分查找作为程序员的一项基本技能,是面试官最常使用来考察程序员基本素质的算法之一,也是解决很多查找类题目的常...
    Jesse1995阅读 2,189评论 0 0
  • 1.旋转数组(189 - 中) 题目描述:给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。进...
    _code_x阅读 1,695评论 2 3