每日刷题!二分查找 移除元素

570 阅读2分钟

重新刷题Day1

其实之前有刷过一次随想录了,还有一些每日一题 ,但是总是断断续续的 没有形成良好的习惯 ,或者说每次刷着都是草草了事 ,刷过也忘了 ,今日一会想大概从去年十一月底就没刷了 三个月过去 又忘得差不多了,临近秋招,从三月开始 ,重新刷题!改变心态! 冲冲!

二分查找

  • < leetcode.cn/problems/bi…>

  • 二分法是非常常见的算法 会应用到各种类型的题目当中去 ,二分法有俩种写法

    一种是左闭右闭区间,另一种是左闭右开区间

    • while (left <= right) 因为left == right是有意义的,所以使用 <=。if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1。ps 刚才自己做题的时候就没写 -1和 +1直接赋值middle了 麻!
    • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的。if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
  • 代码:

  • var search = function(nums, target) {
        // right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
        let mid, left = 0, right = nums.length - 1;
        // 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
        while (left <= right) {
            // 位运算 + 防止大数溢出
            mid = left + ((right - left) >> 1);
            // 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
            if (nums[mid] > target) {
                right = mid - 1;  // 去左面闭区间寻找
            } else if (nums[mid] < target) {
                left = mid + 1;   // 去右面闭区间寻找
            } else {
                return mid;
            }
        }
        return -1;
    };
    var search = function(nums, target) {
        // right是数组最后一个数的下标+1,nums[right]不在查找范围内,是左闭右开区间
        let mid, left = 0, right = nums.length;    
        // 当left=right时,由于nums[right]不在查找范围,所以不必包括此情况
        while (left < right) {
            // 位运算 + 防止大数溢出
            mid = left + ((right - left) >> 1);
            // 如果中间值大于目标值,中间值不应在下次查找的范围内,但中间值的前一个值应在;
            // 由于right本来就不在查找范围内,所以将右边界更新为中间值,如果更新右边界为mid-1则将中间值的前一个值也踢出了下次寻找范围
            if (nums[mid] > target) {
                right = mid;  // 去左区间寻找
            } else if (nums[mid] < target) {
                left = mid + 1;   // 去右区间寻找
            } else {
                return mid;
            }
        }
        return -1;
    };
    

移除元素

  • leetcode.cn/problems/re… 链接

  • 刚开始觉得自己可以瞬间秒杀 不使用暴力方法 没想到写了半小时 还不是双指针 不知道自己之前刷题怎么刷过去的 附上自己的解法 勿喷。

    var removeElement = function(nums, val) {
        let len = nums.length
        nums.sort((a,b) => a-b)
        let res = 0
        let left = 0
        let right = len - 1
    
        while(left < len){
            if(nums[left] !== val){
                left++
                continue
            }
            if(nums[left] == val){
                res++
                nums[left] = nums[right]
                right--
                left++
            }
           
        }
        return len - res
    };
    
    • 先排序 然后left查找删除元素 使用res计数,如果val后面还有别的元素 复制到前面去,最后直接返回删除后的元素个数
  • 暴力解法 双循环

    • 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 = (nums, val) => {
          let k = 0;//慢指针,i就是快指针
          for(let i = 0;i < nums.length;i++){
              if(nums[i] != val){
                  nums[k++] = nums[i]
              }
          }
          return k;
      };
      

theme: juejin