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

704.二分查找

  今日学习文章链接

  第一想法

    题目要求在nums中寻找与target相等的元素的下标,首次想法是暴力解法,代码如下:

var search = function(nums, target) {
  for(let i=0;i<nums.length;i++){
      if(nums[i]<target) continue
      if(nums[i]===target) return i
      if(nums[i]>target) return -1
  }
  return -1
};

代码质量:

 之后觉得二分查找也可以,代码如下(也是左闭右闭的写法)

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

代码质量

 看完文章讲解后的想法

通过代码随想录中关于二分查找的讲解,发现有两种写法,分类为左闭右开和左闭右闭。以前我常用左闭右闭的写法,今日来学习一下左闭右开的写法(本人正在学习ts,所以左闭右开的写法为ts

function search(nums: number[], target: number): number {
   let left:number =0
   let right:number=nums.length
   while(left<right){//此时是左闭右开的写法
    let middle:number=~~((left+right)/2)//向下取整
    if(nums[middle]<target) left=middle+1
    if(nums[middle]>target) right=middle //这里是因为按照左闭右开的写法,可能解的范围为left~right-1
    if(nums[middle]==target) return middle
   }
   return -1
};

代码质量

 思考

二分查找主要为两种写法,左闭右闭和左闭右开,区别在于区间的范围和缩小范围是右边界

左闭右闭的写法:

while(left<=right){//左闭右闭
...
if(nums[middle]>target) right=middle-1 //这里之所以是middle-1,原因是左右都是闭区间,所以right取middle是由判断条件可知是不成立的,所以right取middle-1
...
}

左闭右开写法:

while(left<right){ //这里是左闭右开的写法
...
if(nums[middle]>target) right=middle//这里是middle的原因是右边界是开区间,所以middle取不到,如果是middle-1的话middle-1这个下标的元素就无法取到,可能就错过了目标结果
...

}

27.移除元素

文章学习链接

第一想法

        利用js自带的splice方法解决以上问题,代码如下:

var removeElement = function(nums, val) {
    for(let i=0;i<nums.length;i++){
      if(nums[i]==val){
        nums.splice(i,1)
        i-- //因为splice会改变原数组,所以删除元素后,刚刚删除元素的下标会被后面一位元素占据,所以这里i--需要重新判断当前下标是否等于val
      }
    }
    return nums.length
};

代码质量:

  看完文章讲解后的想法

看完代码随想录后,发现这道题可以用暴力和双指针的解法,于是尝试用这两种解法解决问题

暴力解法:

 //暴力写法
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-- //这里i--的原因是重新判断移到这一位的元素是否等于val
           len--
       }
   }
   return len
};

代码质量:

 双指针解法:

 //双指针
var removeElement = function(nums, val) {
  let slow=0
  //慢指针用于确定新数组的下标 快指针用于寻找非val的元素
  for(let i=0;i<nums.length;i++){
    if(nums[i]!=val){
        nums[slow]=nums[i]
        slow++
    }
  }
  return slow
};

代码质量:

 思考

这道题的主要思路为用后方的元素把等于val的元素覆盖掉(逐一覆盖),所以暴力法应该是最先想到的,遇到等于val的则将当前下标之后的往前移动一位。两层for循环时间复杂度为O(n^{2})

优化:

两层for循环的目的就是让不等于val的元素往前移,所以双指针完全可以解决问题,快指针用于寻找非val元素,slow用于确定新数组下标。

今日总结

今天是参加代码随想录算法营的第一天,之前零零散散刷过一些题,这是第一次系统的学习算法。今日花费时间约2h,算是中规中矩吧。二分查找一般能想到,但是对于双指针有点想不到,还得继续努力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值