Leetcode(一):数组、链表部分经典题目详解(JavaScript版)

一、数组

1. 二分查找

点击跳转到力扣题目

注意题目的前提条件:有序数组、无重复元素

解法:双指针

这道题目的难点在于边界的确定,[left,right][left,right)的边界处理是不一样的,前者right应该为nums.length-1,后者right应为nums.length

第一种:左闭右闭,即从[left,right]区间搜索,以[1,2,3,4],找1为例子带进去看看第一轮while循环

var search = function(nums, target) {
   
   let left = 0; //左指针闭区间,指向第一个位置0
   let right = nums.length - 1; //右指针闭区间,指向最后一个位置3

   //由于是左闭右闭,那么left=right就是有意义的,代表一直找到了最后一个元素
   while(left <= right) {
   
       let middle = Math.floor((right - left)/2) + left //寻找中间位置1
       //开始二分查找,不断缩小边界
       if(target < nums[middle]) {
   
      	   //缩小边界,由于right是闭区间,判断条件已经确定target<middle位置的值
      	   //由于是闭区间,下一次搜索一定会搜索<=middle-1处的值,right要变为middle-1=0
           right = middle - 1; 
       } else if (target > nums[middle]) {
   
           left = middle + 1;//缩小边界,此时已确定target>middle位置的值,left要变为middle+1
       } else {
   
           return middle //如果中间位置这个数刚好对上,就返回,否则就会一直到循环的最后一轮
       }
   }
   //如果没有return,就return-1
   return -1
};

第一轮循环结束后,搜索区间变成了[0,0],也就是左右指针都指向了位置0的元素1,此时左右指针相撞,left=right就是有意义的,所以while循环的条件就是<=,等于号的情况代表一直找到了最后一个元素

第二种:左闭右开,即从[left,right)区间搜索,以[1,2,3,4],找1为例子带进去看看第一轮while循环

var search = function(nums, target) {
   
   let left = 0; //左指针闭区间,指向第一个位置0
   let right = nums.length; //右指针开区间,指向最后一个位置3的后面4

   //由于是左闭右开,那么left=right就是没有意义的
   while(left < right) {
   
       let middle = Math.floor((right - left)/2) + left //寻找中间位置1
       //开始二分查找,不断缩小边界
       if(target < nums[middle]) {
   
      	   //缩小边界,由于right是开区间,判断条件已经确定target<middle位置的值
      	   //由于是开区间,下一次搜索一定会搜索<middle的值,right要变为middle=1
           right = middle; 
       } else if (target > nums[middle]) {
   
      	   //缩小边界,由于left是闭区间,判断条件已经确定target>middle位置的值
      	   //由于是闭区间,下一次搜索一定会搜索>=middle+1的值,left要变为middle+1	       
           left = middle + 1;
       } else {
   
           return middle //如果中间位置这个数刚好对上,就返回,否则就会一直到循环的最后一轮
       }
   }
   //如果没有return,就return-1
   return -1
};

第一轮循环结束后,搜索区间变成了[0,1),也就是左指针指向了位置0的元素1,右指针指向了位置1的元素2,此时必然会锁定0位置的元素,所以while循环的条件就是<

这个题有点不太好描述,感觉容易乱,先这样吧……我觉得最好按第一种方法来记

2. 移除数组元素

点击跳转到力扣题目
做这道题必须要知道数组的特点,那就是删除元素时只能覆盖,不是原地删除

解法:快慢指针法

想要用快慢指针法解这个问题,最关键的点就是理解slow和fast都代表什么
我们可以把慢指针理解为新数组的每个位置,快指针的作用是遍历整个数组,这样的话快指针只需要找到不用删除的元素,然后依次覆盖就可以了。
可以仔细看下注释,以removeElement([1,2,3,4],3)理解一下指针的移动过程

var removeElement = function(nums, val) {
   
    let slow = 0; //慢指针,指向新数组的每个位置
    for(let fast = 0; fast < nums.length; fast++) {
    //快指针fast遍历数组
        if(nums[fast] !== val) {
       
            //如果快指针指向的不是要删除的元素,那么就让快指针位置的值覆盖慢指针位置的值
            nums[slow] = nums[fast]
            slow++ //然后慢指针先移动,快指针再移动
        }
        //如果是要删除的元素,那么只有快指针移动(fast++),慢指针不动
        //这样可以做到后面的值覆盖到当前慢指针指向的位置
    }
    //移除后数组长度,就是当前slow指向的这个索引
    return slow //因为如果覆盖了当前元素,slow会先往后移,此时指向的是没有元素的位置
    //比如[1,2,3,4],删除3时,slow指向3,fast指向4,4覆盖3后slow指向4,此时索引为3,正好是数组长度
};

3. 有序数组的平方

点击跳转到力扣题目

解法:双指针法

这个题目相较于前面两个,更好理解一些,其实也可以先平方再快排,但是更好的是用空间换时间,使用双指针法,依次找最大的元素unshift,当两个指针相撞时,就是最小的那个元素。

//双指针法,空间换时间,时间复杂度O(N)
 var sortedSquares = function(nums) {
   
    let i = 0;   //一个指针指向头部
    let j = nums.length - 1;  //一个指针指向尾部
    let result = []; //开辟一个新的空间
   //注意循环停止的条件,当i = j时,指针相撞,指向的应该是最小的元素,循环应继续
    while(i<=
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值