代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。

163 阅读3分钟

704. 二分查找

题目链接

leetcode.cn/problems/bi…

文章链接

programmercarl.com/0704.%E4%BA…

视频链接

www.bilibili.com/video/BV1fA…

看到题目的第一想法

我看到这道题的第一想法并不是用二分查找法来做,而是直接用for循环来依次遍历,直到找到要查找的元素为止,下面附上我的go语言代码:

func search(nums []int, target int) int {
    for i := 0; i < len(nums); i++ {
        if nums[i] == target {
            return i
        }
    }
    return -1
}

这段代码并没有用二分查找法来做,但是这种做法针对于这道题是可取的,但是我并不知道二分查找法的代码该怎样写,所以之后去学习了代码随想录的视频和文章,看了一下卡哥的思路和代码。

看完代码随想录之后的想法

卡哥在视频中讲到了定义两个变量,一个是left,一个是right,在循环中用left和right的中间值和target作比较,所以还可以定义一个变量middle,用nums[middle]和target比大小,如果大于target,就取left到middle这段区间,如果小于target,就取middle到right这段区间,直到left大于right(注意,left不可能大于right,循环条件应该定义为left <= right),此时退出循环,这时的middle就是target的下标了。下面附上我的go语言代码:

func search(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right {
        middle := left + (right-left)/2;
        if nums[middle] < target {
            left = middle + 1
        } else if nums[middle] > target {
            right = middle - 1
        } else {
            return middle
        }
    }
    return -1
}

实现过程中遇到的困难

卡哥在视频中也提到了,二分查找法一般会用到左闭右闭区间和左闭右开区间,这道题我用的是左闭右闭区间,没有用到左闭右开区间,这里会涉及到临界值的取舍问题,我当时也比较纠结,后来一想,既然闭区间能够取临界值,那么middle就不能取临界值,所以会出现middle+1和middle-1的操作,这个仔细想想就不难理解了。

今日收获

今天学会了二分查找法的基本思路以及代码的编写,也理解到了二分查找法的注意事项,也就是关于临界值的判断,middle是否加减1,细节决定成败,这个是我今天最大的收获。

27. 移除元素

题目链接

leetcode.cn/problems/re…

文章链接

programmercarl.com/0027.%E7%A7…

视频讲解

www.bilibili.com/video/BV12A…

看到题目的第一想法

我看到这道题返回值是一个数,不是数组,暗自窃喜,定义一个变量count计数,只要是元素的数值不等于val,count自增1,数值等于val的元素时,count保持不变,不就做出来了吗?结果执行代码过后发现题干给出的测试用例,我的输出结果都不对,后来发现我的想法只能输出前count数量的元素,之后的元素就输不出来了。举个例子,就拿题干中的测试用例来说,输入:nums = [3,2,2,3], val = 3。输出:2, nums = [2,2]。而我的输出结果是[3,2],移除了两个元素是对的,但是我的代码只能输出第1个元素和第2个元素,而测试用例移除的是第1个和第4个元素,应当输出第2个元素和第3个元素。所以我的想法并非移除。

看完代码随想录之后的想法

看完代码随想录,我发现我想错了,从视频中,卡哥说了可以使用暴力的方法,也就是for循环嵌套来解决此题,但是这道题最好用双指针法来做,用快慢指针,一个fast,一个slow,最开始先同时走,当某个元素的数值为val时,fast依然继续走,slow停一步,将fast指针指向的值赋值给slow指针指向的值,就这样当fast指针走到了数组的尽头,返回slow,这时的数组才是移除元素过后的数组。以下附上我的go语言代码:

func removeElement(nums []int, val int) int {
    fast, slow := 0, 0
    for fast = 0; fast < len(nums); fast++ {
        if nums[fast] != val {
            nums[slow] = nums[fast]
            slow++
        }
    }
    return slow
}

实现过程中遇到的困难

最开始将nums[slow] = nums[fast]这句代码写掉了,得到的结果还是我的第一想法的结果,后来才发现没有重新赋值,所以我专门将fast赋值给slow给加粗了。

今日收获

今天的收获就是我小看了这道题,这道题主要考察双指针用法,看来我还得要花时间熟练这种用法。