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

434 阅读3分钟

704.二分查找

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

思路
设置两个指针指向数组头尾,取头尾中间值与目标值比较。
如果中间值大,取前半部分(左指针到中间值)进行查找;
如果中间值小,取后半部分(中间值到右指针)进行查找;
如果中间值等于目标值,返回中间值,即目标值下标;
如果查找不到,返回-1。

注意
分为左闭右开和左闭右闭两种情况:

  • 左闭右闭情况下,左指针等于右指针有意义,并且每次取边界值需要排除原来取过的左右指针
  • 左闭右开情况下,左指针不等于右指针,并且每次取右边界值可以与原来的右指针重合

代码

// 左闭右开
const search = (nums, target) => {
  if (target < nums[0] || target > nums[nums.lengt - 1]) return -1

  let mid, left = 0, right = nums.length

  while (left < right) {
    mid = left + ((right - left) >> 1)
    if (nums[mid] > target) right = mid
    else if (nums[mid] < target) left = mid + 1
    else return mid
  }
  return -1
}
// 左闭右闭
const search = (nums, target) => {
  if (target < nums[0] || target > nums[nums.lengt - 1]) return -1

  let mid, left = 0, right = nums.length - 1

  while (left <= right) {
    mid = left + ((right - left) >> 1)
    if (nums[mid] > target) right = mid - 1
    else if (nums[mid] < target) left = mid + 1
    else return mid
  }
  return -1
}

总结
之前学Java的时候对这个题目刷的贼熟,半年没刷回来用js发现大概结构还记得,但是对这道题的核心考察还是没记住,看了一下之前写的Java代码写出来的。同时在看别的大佬的js题解时学会了>>右移运算符的使用。

27.移动元素

题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

思路
设置左右两个指针,设置一个左指针小于右指针的循环,分别从左往右、从右往左移动检索,如果左指针等于目标值暂停左指针移动,如果右指针不等于目标值暂停右指针移动,然后判断左指针是否小于右指针,小于的话就把左右指针的值互换,然后继续循环,否则跳出循环,最后得到的数组应该是所有目标值都在数组最后,然后返回第一个目标值的索引值,就是有效值的长度。

注意
在对左右指针的值进行互换之前要额外比较一下左指针和右指针的大小,因为每次循环开始时,左右指针要重新移动一次。

代码

// 莫名其妙解法
ar removeElement = function (nums, val) {
  if (!nums.includes(val)) return nums.length
  let left = 0, right = nums.length - 1
  while (left <= right) {
    while (nums[left] !== val) {
      left++
    }
    while (nums[right] === val) {
      right--
    }
    if (left >= right) break
    nums[left] = nums[right]
    nums[right] = val
  }
  return nums.indexOf(val)
};

总结
发现力扣里面之前自己用Java做过,但是没啥印象,应该是看着代码随想录做的,这次是自己硬想出来的,但是感觉有点怪怪的。

优化:

ok看了一下代码随想录的解法是快慢指针,我还以为自己做的很不错,原来自己做的莫名其妙,看完一遍解题思路后,自己重新做一遍。

优化后代码

// 快慢指针法(自己写)
var removeElement = function(nums, val) {
    let size = nums.length,slowIndex = 0
    for (let fastIndex = 0; fastIndex<nums.length;fastIndex++){
        while (nums[fastIndex] === val) {
            fastIndex++
            size--
        }
        nums[slowIndex++] = nums[fastIndex]
    }
    return size
};

// 快慢指针法(看答案)
var removeElement = function(nums, val) {
    let slowIndex = 0
    for (let fastIndex = 0; fastIndex<nums.length;fastIndex++){
        if (nums[fastIndex] !== val) {
            nums[slowIndex++] = nums[fastIndex]
        }
    }
    return slowIndex
};

Day1总结

第一天的算法题应该还是比较简单的,但是自己还是做了快2小时吧,尤其是写算法的时候逻辑不是很清晰,感觉自己很菜,但是对算法又有一种新鲜感,刷题的时候感觉还是挺有趣的。