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

274 阅读2分钟

练习时长两年半的小趴菜开始的算法之路

leetcode 704.二分查找

题目链接: 704.二分查找

题目分析

该题目是在有序数组中,寻找一个数字,然后返回其对应要求的值 使用 二分法 效率比较高

解法:左闭右开

左闭右开即 [left, right)

function search(nums: number[], target: number): number {
    let left = 0
    let right = nums.length // 注意
    while (left < right) { // 注意
        const mid =left + ((right - left) >> 1)
        if(target < nums[mid]) {
            right = mid // 注意
        } else if (target > nums[mid]) {
            left = mid + 1
        } else if (target == nums[mid]) {
            return right = mid
        }
    }
    return nums[left] == target ? left : -1 // 注意边界问题
};

解法:左闭右闭,也称为两端闭合

两端闭合即 [left, right]

function search(nums: number[], target: number): number {
    const len = nums.length
    let left = 0
    let right = len - 1
    while (left <= right) {
        const mid = Math.floor(left + (right - left) / 2)
        if(target == mums[mid]) {
            return mid
        } else if(target < nums[mid]) {
            right = mid - 1
        } else if (target > nums[mid]) {
            left = mid + 1
        }
    }
    return -1
};

对比

左闭右开两端闭合
right取值数组长度数组长度-1
while<<=
数组不存在目标元素时需要判断边界问题直接return -1
target < nums[mid]right = midright = mid - 1

leetcode 27.移除元素

题目链接:27.移除元素

题目分析

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

所以该题目不能删除只有做覆盖

解法:暴力双循环

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

解法:双指针

function removeElement(nums: number[], val: number): number {
    let slow = 0
    for( let fast = 0; fast <nums.length; fast++) {
        if(val !== nums[fast]) {
            nums[slow] = nums[fast]
            slow++
        }
    }
    return slow
};

总结&注意

总结

之前也断断续续的刷过几道二分法的题,只理解了两端闭合的写法,这次巩固了左闭右开的写法,下去也得多多练习

1. 二分法

  1. 二分法整体思路不难,难在 mid(中间值) 是 +1 还是 -1; while 中用 <= 还是 <
  2. 取中间值用 left + (right -left) / 2left + (right -left) >> 1, 不要用 (left + right) / 2 在计算中可能会产生溢出问题,即上述可以改为 image.png
  3. 逻辑运算符(+``-``*``/) 优先级在 位运算 之前,即上述使用位运算时需要加上括号 left + ((right-left) >> 1)

2. 双指针

  1. 快慢指针法: fast 快指针用来查找元素, slow 慢指针用来处理操作
  2. 数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

参考资料:

1.数组理论基础

2.位运算 >>

最后,文章有不对的地方请各位大佬指出!!!