数组篇: 704.二分查找、27.移除元素

提示:努力生活,开心、快乐的一天

文章目录

  • 704.二分查找
    • 解题思路
    • 遇到的问题
    • 代码实现
    • 题目总结
  • 27、移除元素
    • 解题思路
    • 遇到的问题
    • 代码实现
    • 题目总结
  • 今日心得


704.二分查找

题目链接:704.二分查找

解题思路

  1. 二分查找的前提条件:有序数组+无重复元素
  2. 题目中数组的左右边界,主要分为2种边界:[left,right]和[left,right)
  3. 坚持循环不变量原则,此题中的不变量就是区间
  4. 边界处理
    [left,right]
  • nums[mid]>target时,需要更新右边界的值,right = middle-1(此处!=middle的原因是:遵循区间不变原则,右区间为闭区间,则nums[mid]可能等于target,但进入该判断条件的前提是nums[mid]>target,两者相悖,所以!=middle);

  • nums[mid]

[left,right)

  • nums[mid]>target时,此时需要更新右边界的值,right = middle(此处=middle的原因是:遵循区间不变原则,右区间为开区间,则nums[mid]不可能等于target,但进入该判断条件的前提是nums[mid]>target,两者一致,所以=middle);

  • nums[mid]

遇到的问题

  1. mid的取值问题,(left+right)/2 会产生溢出情况
    解决方案:使用 >> 运算符

  2. 边界处理上,一看就会,一些就废,眼高手低啦

代码实现

[left,right]

var search = function (nums, target) {
    let left = 0;
    let right = nums.length - 1;
    while (left <= right) {
        let mid = (right + left) >> 1
        if (nums[mid] > target) {
            right = mid - 1
        } else if (nums[mid] < target) {
            left = mid + 1
        } else {
            return mid
        }
    }
    return -1;
};

[left,right)

var search = function (nums, target) {
    let left = 0;
    let right = nums.length;
    while (left < right) {
        let mid = (right + left) >> 1
        if (nums[mid] > target) {
            right = mid
        } else if (nums[mid] < target) {
            left = mid + 1
        } else {
            return mid
        }
    }
    return -1;
};

题目总结

  1. 数组满足二分查找的条件
  2. 确定查找的区间,是[left,right]还是[left,right)
  3. mid取值不可溢出,使用 >> 运算符
  4. 对于 [left,right]
    right 值就是数组最后一位的下标
    while 循环的条件遵循区间不变规则, left<=right
    判断条件分3种情况:
    nums[mid] > target :target值在左区间,更新右区间值为[left,mid-1]
    nums[mid] < target :target值在右区间,更新右区间值为[mid+1,right]
    nums[mid] = target :return mid
    不满足循环,return -1
  5. 对于[left,right)
    right 值就是数组的长度
    while 循环的条件遵循区间不变规则, left
    判断条件分3种情况:
    nums[mid] > target :target值在左区间,更新右区间值为[left,mid)
    nums[mid] < target :target值在右区间,更新右区间值为[mid+1,right)
    nums[mid] = target :return mid
    不满足循环,return -1

27、移除元素

题目链接:27.移除元素

解题思路

  1. 原地移除元素,所以不能new一个新的数组
  2. 暴力解法:双层for循环,第一层,遍历数组;某元素与val值相同时,进行第二层循环,将其后的元素往前移动,时间复杂度: O(N^2),空间复杂度:O ( 1 )
  3. 双指针解法:定义快慢两个指针,fast指针代表新数组的元素,slow指针代表新数组的下标,当fast指针遇到val时,直接跳过,等待 slow指针将其覆盖,从而达到删除元素的效果;如果 fast 指针遇到值不等于val的元素,将其值赋值给 slow 指针,然后让 slow 指针前进一步。

遇到的问题

  1. 循环时不自觉就写成给nums.length-1
  2. 暴力解法时,第一层循环向前移动一位时,错写成江第二层循环往前移动一位

代码实现

暴力解法

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

双指针解法

var removeElement = function (nums, val) {
    //双指针
    let slow = 0
    for (let i = 0; i < nums.length; i++){
        if (nums[i] !== val) {
            nums[slow] = nums[i]
            slow++
        }
    }
    return slow;
};

题目总结

双指针经常用于处理数组和链表相关问题,主要利用了数组连序性的特点。优点是降低算法的时间复杂度,因为使用两个指针可以避免多层循环。双指针技巧主要分为两类:左右指针快慢指针。本题使用到了快慢指针

今日心得

一边上班一边刷题,先看题,发散思维,梳理自己的思路,再看视频,再看文字版解析,再编码,最后写博客(第一次写,很浪费时间)。时间比较散,因为偶尔对需求,偶尔改bug,偶尔开会。但还是完成了。欣崽棒棒哒

你可能感兴趣的:(算法,算法,javascript,前端)