代码随想录|day1 二分查找、移除元素

106 阅读2分钟

二分查找

题目链接:leetcode.cn/problems/bi…

思路:

定义二分区间。取中间值mid,对比给定值target,mid > target 缩右区间,反之则缩左区间,反复缩减区间直至target与mid相等则找到target位置

重点:

  • 确定二分区间的边界,也就是循环不变量。不可以这次循环中区间左闭右开,下次又左闭右闭的

  • 每次缩减区间的边界值处理。

代码

/**
 * 二分查找
 * @param {number[]} nums [-1,0,3,5,9,12]
 * @param {number} target 9
 * @return {number}
 */
var search = function (nums, target) {
  // 第一种解法,左闭右闭区间
  let left = 0,
      right = nums.length - 1;
  while (left <= right) {
    let mid = left + Math.floor((right - left) / 2);
    if (target > nums[mid]) {
      left = mid + 1;
    } else if (target < nums[mid]) {
      right = mid - 1;
    }else{
      return mid
    }
  }
  return -1 
};
var search = function (nums, target) {
  // 第二种解法,左闭右开区间
  let left = 0,
    right = nums.length;
  while (left < right) {
    let mid = left + Math.floor((right - left) / 2);
    if (target > nums[mid]) {
      left = mid + 1;
    } else if (target < nums[mid]) {
      right = mid;
    } else {
      return mid;
    }
  }
  return -1;
};

总结

左闭右开确定二分区间的边界,左缩减区间更改 left = mid+1 而不是 mid。这里我第一次写时,理所应当写了 left = mid,忘记了区间左闭。

大错特错!看了代码示例后又想起卡哥说的要牢记区间定义才能判断好缩减区间时边界取值,left等于 mid 还是 mid+1。(可恶,有那种开卷答题却0分的感觉)

逻辑就是这么个逻辑,牢记重点:确定循环不变量才能处理好边界取值

移除元素

题目链接:leetcode.cn/problems/re…

暴力解法

思路:

for 循环,当 nums[I]等于 target 时,删除该元素,I - -  

for 循环,当 nums[I]等于 target 时,再for循环。将后一位往前移一位

重点:

for 循环结束条件 len,而不能些用nums.length,因为 len 是动态变化的,每次找到相等的我们就需要变更 len

移动后一位元素至当前,nums[j-1] = nums[j] 不能是 nums[i] = nums[j]。因为此时在 j 的循环中,i 是不变的,要讲每个元素移至前一个必须是 nums[j-1]

代码

/**
 * 移除元素
 * 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2,_,_]
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function (nums, val) {
  // 解法 1
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === val) {
      nums.splice(i, 1);
      i--;
    }
  }
  return nums.length;
  
  // 解法 2
  // let len = nums.length;
  // for (let i = 0; i < len; i++) {
  //   if (nums[i] === val) {
  //     i--;
  //   }
  // }
  // return len; 
};

双指针

之前刷过一遍,但是单看题目还是没有思路,需要查看题解视频。

思路:通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

重点

  • 确定快慢指针的含义
  • 快指针: 遍历数组,寻找新数组的元素
  • 慢指针: 指向新数组的下标

代码

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

总结

秒啊!总之明确快慢指针的含义,才不容易出错。