✅ ✅ 代码随想录算法训练营Day1 | | 704. 二分查找、27. 移除元素

266 阅读3分钟

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

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第5篇文章 点击查看文章详情 🚀🚀

前言

来咯来咯~

这一次终于狠下心,要对算法下死手了!!!

没错,这次我加入了卡哥的算法训练营,准备花两个月的时间,每天写一篇博客,刷150个算法题!!!

期待两个月后遇见更好的自己! ⭐⭐⭐

题目安排

题解实现过程

704. 二分查找 - 力扣(LeetCode)

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,
写一个函数搜索 nums 中的 target,
如果目标值存在返回下标,否则返回 -1。


示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

自己刚开始的思路是直接暴力搜索,但后面看见题目名字都叫二分查找了,再直接用暴力搜索就不太礼貌了~

咳咳咳,然后我这个菜鸡自己傻傻的用递归捣弄不出来,就去看卡哥的视频了。👉 二分查找视频

文章+视频后,还是有一些难点

难点

中点的计算

一般来说,我们计算中点时,直接用

 mid = (left + right)/2 

但往往我们也会发现这一种形式

 mid = left + (right-left) / 2

甚至

 mid = left + ((right-left) >> 1)

具体的区别可以再参考这篇文章👉 求数组中间值的三种方法_Lytis的博客-CSDN博客_找中间数的简便方法

自己理解的意思是

当left,right的范围给的很大,大到要超过数值范围时, 我们就不能用 mid = (left + right)/2 ,以免发生溢出问题。 而 mid = left + (right-left)/2 却可以很好的解决这个问题。

区间的范围

到底是左闭右开,还是左闭右闭?

产生这个问题的原因是,我们刚开始会查找中点,通过这个中点进行下一步区间范围的划定。

在这个范围划定的时候就出现了两种方式

在这里我只解释左闭右闭这种形式,另外一种也是类似的。

回到范围的划定

按照左闭右闭的方法,即两边的值都能取到

所以下一个范围不包括中点~

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
  
    let l = 0;
    let r = nums.length-1;
    
    // 考虑了当查找的值正好是在初始范围的最两侧
    // 迭代的方式
    while(l <= r){
    // 不要忘了要向下取整
        let mid = Math.floor(l + (r-l) / 2) 
        if(nums[mid] < target ){
            l = mid + 1; // 不包括中点
        }
        else if(nums[mid] > target){
            r = mid - 1; // 不包括中点
        }
        else{
            return mid
        }
    }
    return -1

};

收获

  • 对中点的计算方式更加理解

  • 掌握了两种区间范围

    左闭右开

    左闭右闭

27. 移除元素 - 力扣(LeetCode)

还是老样子,只能想到暴力解法。

var removeElement = function(nums, val) {
     let len = nums.length;
     for(let i = 0;i < len;i++){
        if(nums[i] == val){
             for(let j = i;j < len;j++){
                nums[j] = nums[j+1];
             }
            len = len -1;
            i = i - 1;
        }
     }
     return len;
};

两层for循环,

第一层for循环用来寻找要移除的元素

第二层for循环

1. 后面的值覆盖前面的值
2. 再将后面的值进行移动

又又又看了一波卡哥的视频👉视频

难点

数组的基础

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

双指针 快慢指针

对我来说双指针的应用场景还比较少,所以也算一个难点。

代码

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    // 设置快慢指针  fast slow
    let slow = 0;
    let len = nums.length;
    for(let fast = 0;fast < len ;fast++){
        if(nums[fast] != val){
            nums[slow] = nums[fast];
            slow++;
        }
    }
    return slow;
};

收获

熟练了对双指针的使用

小结

今天是第一天,加上写文章,花了差不多四个小时,还行!

收获也不少,让我重拾了刷算法的自信!

希望后面继续保持!

😁😁😁