小马的力扣日记Day1 二分查找 704.278.35

一.二分法

简介

二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。

工作原理

以在一个升序数组中查找一个数为例。

它每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值同理,只需到左侧查找。

性质

二分查找的最优时间复杂度为 O(1)

二分查找的平均时间复杂度和最坏时间复杂度均为 O(logn)。因为在二分搜索过程中,算法每次都把查询的区间减半,所以对于一个长度为 n 的数组,至多会进行O(logn) 次查找。



二.题号704 二分查找

题目

思路

问题是标准的二分思想。

1.以有序数列的上下界为初始搜索上下界。

2.取当前搜索上下界的均值作为搜索索引。

3.若搜索索引对应的值大于需要搜索的Target,则收缩搜索上界,将当前索引值作为新的搜索上界,重复2;

  若搜索索引对应的值小于需要搜索的Target,则收缩搜索下界,将当前索引值作为新的搜索下界,重复2;

  若搜索索引对应的值等于需要搜索的Target,则找到,返回搜索索引值。

4.Case 1:Target不存在于此数组,即搜索上下界重合,此时返回-1。

  Case 2:只有两个数的时候,即上界-下界=1,则退出循环,直接看这2个数是否等于Target,没有就返回-1。

  Case 3:初始就只有1个数的时候,就一开始没考虑到这一点,导致下标报错!

代码

class Solution {

public:

    int search(vector<int>& nums, int target) {

        int highbound,lowbound=0;

        int index=0;

        //Case 3:Only 1 number in given array

        if (nums.size()==1)

            {

            if (nums[0]==target)

                return 0;

            else

                return -1;

            }

        highbound= nums.size()-1;


        //Case1:More than 2 numbers to be scanned

        while(highbound-lowbound>1){

            index=int((lowbound+highbound)/2);

            if (nums[index]==target)

                return index;

            else {

                if (nums[index]>target)

                    {

                        highbound=index;

                    }

                    else lowbound=index;

            }

        }

        //Case2:Only 2 or less number to be scanned

        if (nums[lowbound]==target)

            return lowbound;

        else if (nums[highbound]==target)

            return highbound;

            else return -1 ;

    }

};

反思


1.我要打死那些百度回答,说C++数组长度只能用sizeof(arr)/sizeof(int)来取,我给试了半个小时都还是报溢出。结果我突然试试arr.size()就解决了。谁能想到在这种细节上挣扎了半个小时, WTF

2.漏考虑了初始数组的极端情况,不仅是查找缩界的时候可能出现只有1个或者2个数的情况,初始的数组也完全有可能出现1个或者2个数。


三.题号278 第一个错误的版本

题目

思路

二分查找的变种问题

相较于标准的二分查找,本题的变更点在于上下界的收缩条件。

原二分查找是根据Target和上下界均值索引所指向元素的大小关系来进行缩界。

本题的缩界条件是:

1.若均值索引所指元素是Good Version,收缩下界为该索引。

2.若均值索引所指元素是Bad Version,收缩上界为该索引。

必须考虑的情况有:

Case 1:初始只有一个版本,那么必为Bad

Case 2:初始只有两个版本,直接判断第一个是否为Bad,如果不是,那第二个一定是Bad

Case 3:正常情况下,Good 和Bad 的边界会逐渐缩进到相邻两个元素,那么此时的搜索上界就是Bad


代码

// The API isBadVersion is defined for you.

// bool isBadVersion(int version);

class Solution {

public:

    int firstBadVersion(int n) {

        //Case 1: Only 1 version

        if (n==1)

        return 1;

        //Case 3 : More than 2 version

        int lowbound=1;

        unsigned int highbound=n;

        unsigned int index=0;

        if (isBadVersion(1))

            return 1;

        while (lowbound<(highbound-1))

        {

            index= int((lowbound+highbound)/2);

            if (isBadVersion(index)){

                  highbound=index;

            }


            else

            {

                lowbound=index;

            }

        }   

        return highbound;

    }

};


反思

1.要求是尽可能减少isBadVersion()接口的调用,所以在Case 1 只有一个版本的情况下,这个版本不用调用接口去判断,一定是Bad,直接可以返回1。在Case 2 有2个版本的情况我在实际编码时发现可以归到Case 3中去,那么我就减去了Case 2 单独的判断代码,减少一个时间复杂度O(1)的操作。

2.实际测试中发现给出了非常大数值的样例,导致上下界和Index溢出,解决办法就是使用unsigned int,不过空间有些浪费,所以通过对样例的试探,我将Index和上界改成Unsigned int,下界还是维持int。我觉得在空间复杂度这一点上仍然有优化的空间。

四 题号35 搜索插入位置


思路

1.首先拿到感觉像是一个O(n)的插入操作,但是题目要求用logn的算法来做,那明显就是二分查找的变种

2.如果元素在数组中的话,那就是一个基础的二分查找问题。

3.如果元素不在数组中,那么就与原二分查找问题有些不同。在原问题中,如果搜索的上下界已经紧邻但上下界对应的元素都不等于Target,此时就返回不存在。但在本问题中,这个最终的上下界未必就一定是元素应该插入的位置,因为这个元素可能比最后一个元素都要大,也有可能比第一个元素都要小,这样的话,整个数组就都不在其数值范围之内。所以问题就在于如何确定元素不在数组中,以及确定最后一次查找的搜索上下界。

Case 1:初始数组只有一个元素,如果小于等于Target,则返回0,否则返回1.

Case 2:  初始数组有两个以上的元素,首先考虑第一个元素是否大于Target,或者最后一个元素是否小于Target,如果是,直接返回0或者num.length()就行了。

Case 3 :  初始数组有两个以上的元素,且在数组已有的数值范围内,那么就原计划执行二分查找,返回最后的上界值。

代码

class Solution {

public:

    int searchInsert(vector<int>& nums, int target) {

        unsigned int lowbound=0;

        unsigned int index=0;

        unsigned int highbound=nums.size()-1;

        //case 1 : only 1 number

        if (nums.size()==1)

        {

            if (target>nums[0])

                return 1;

            else

                return 0;

        }

        //case 2: more than 2 numbers,but bigger or smaller than any numbers in the given array

        if (target>nums[highbound])

            return nums.size();

        if (target<=nums[0])

            return 0;

        if (target==nums[highbound])

            return nums.size()-1;

        //case 3: more than 2 numbers, and in the range of the given array

        while (highbound>(lowbound+1))

        {

            index=int((highbound+lowbound)/2);

            if (nums[index]==target)

                {

                    return index;

                }

            if (nums[index]>target)

              {

                  highbound=index;

              }

            else

              {

                  lowbound=index;

              }

        }

        if (nums[lowbound]==target)

          {

                return lowbound;

          }     

        else

        {

            return highbound;

        }

    }

};


反思


1.途中犯了条件语句的“==”错误,不应该。

2.本来想偷懒,把Target在头和尾的情况都放到Case 2中,但是实际上返回的值不同,Debug了一会儿。

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

推荐阅读更多精彩内容