leetcode

191 阅读1分钟

leetcode刷题记录

-写在前面:我觉得应该是每天晚上把今天学的东西回顾一下,总结到掘金上面来

-每天的时间应该是 一半算法 一半八股

数组

01.两数之和【easy】

var twoSum = function(nums, target) {
    // 先实例化一个map对象
    let map = new Map()
    // 遍历数组
    for ( let i = 0; i < nums.length; i++){
        // 如果map中有 target-nums[i] 的值,返回该值的下标和 i
        if(map.has(target - nums[i])){
            // 能这样返回的原因是,你在map里面存的是 key:元素值 value:元素索引
            // 所以你在map.get(target-nums[i]) 获得的是 值为map.get(target-nums[i]) 的索引号
            return [map.get(target - nums[i]), i]
        } else{
            // 如果没有符合条件的值 就把我遍历过的 nums[i] 存到map里面去
            map.set(nums[i],i)
        }
    }
}

二分法

看到二分查找记住以下三个重要的点:

1.数组必须有序,否则二分查找算法就会失效, 换而言之,只要看到面试题里给出的数组是有序数组,都可以想一想是否可以使用二分法

2.定义两个指针,left 和 right

3.注意while循环的条件是否包含left = right的情况,同时也要注意中间变量 mid 的算法,防止其出现溢出现象。

红蓝二分法理论讲解

mid = left + ((right - left) >> 1) //二进制里面,右移一位就是除以2 而且这么写能保证一定是整数

一个讲的很好的视频 五点七边_二分法

对于该方法的讲解 文字版讲解

作者:随心源 链接:随心源 来源:力扣(LeetCode)

9GPZ)@PP9F_S@TQ6BZ~~T.png

这个文字版讲解是对该模板的一些特殊情况的处理和说明,我们来看一下:

1.模板中的二分判断条件 哪个方便选哪个

可以写成

if isBlue(m)
    l = m
else
    r = m

也可以写成

if isRed(m)
    r = m
else
    l = m

2.模板中的循环判断条件建议写成l + 1 < r 能够提高运算速度

3.下标边界对应迭代器说明: 开始时,l 指针和 r 指针取在搜索区间界外,另一个重要作用就是构造了下标边界。

4.搜索完毕后的特殊情况: 如果二分查找跳出 while 循环之后,蓝色指针 l === 首个元素下标 - 1,即整个搜索区间都被染成红色,即左边蓝色区域长度为0,如果搜索目标位于左边蓝色区域,则搜索结果不存在,一般需要后处理;

如果二分查找跳出 while 循环之后,红色指针 l === 末尾元素下标 + 1,即整个搜索区间都被染成蓝色,即右边红色区域长度为0,如果搜索目标位于右边红色区域,则搜索结果不存在,一般需要后处理;

5.以下技巧必须掌握:

排序 二分查找的运用是建立在数组有序的基础上的,如果数组无序,我们要先对数组进行排序,如果数组有多个维度,我们针对需要二分查找的维度进行排序。

构造二分查找区间

image.png

image.png

image.png

多维度向量二分查找 有时候我们会遇到一类题我们要一组向量有多个维度,每个维度都要满足某种顺序,即需要对多个维度进行二分查找,但是我们只能对一个维度进行排序,怎么办?这时候我们以一个维度为主键进行排序,另一个维度我们有以下几种处理方式:(见原帖链接)

image.png


红蓝二分法做题

做题的时候,一是构建好输入(看样例要怎么输入),然后可以在主函数中去调用具体的实施函数,然后再把这个实施函数在外面写出来。

下面用蓝红分界法来做一下这些题:

704.二分查找【easy】

我划分的蓝色区域是 蓝色<= target, 红色> target 所以如果数组中有这个值的话 是left指针指向的

var search = function(nums, target) {
   let n = nums.length
   let left = -1, right = n
   while(left + 1 !== right){
       let mid = left + ((right - left) >> 1)
    if(nums[mid] <= target){
        left = mid
    }else{
        right = mid
    }
   }
   if(nums[left] === target) return left
   return -1
};

35.搜索插入【easy】

我划分的蓝色区域是 蓝色<= target, 红色> target

所以在找不到目标元素的时候,即蓝色区域最右边的,left指向的元素不是target时,返回的是 left + 1

var searchInsert = function(nums, target) {
// 这道题和704最大的不同就是如果目标值不存在的时候,704是返回-1
// 这里要求返回目标将会被按顺序插入的位置
   let n = nums.length
   let left = -1, right = n
   // isBlue 的条件是 nums[mid] <= target
   while(left + 1 !== right){
       let mid = left + ((right - left) >> 1)
       if(nums[mid] <= target){
           left = mid
       }
       else{
           right = mid
       }
   }

   //循环结束后
   if(nums[left] === target) {return left}
   else {return left + 1}

};