当前位置: 首页 > news >正文

LeetCode热题100JS(69/100)第十三天|34|33|153|4|20

 34. 在排序数组中查找元素的第一个和最后一个位置

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置

难度:中等

刷题状态:2刷

新知识:

解题过程

思考

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
题解分析

参考题解链接:【视频讲解】二分查找总是写不对?三种写法,一个视频讲透!(Python/Java/C++/C/Go/JS)

放下1刷过程

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
    let start=startPos(nums, target)
    let end=startPos(nums, target+1)-1
    // console.log('start',start)
    // console.log('end',end)
    if(nums[start]!=target){
        return [-1,-1]
    }
    return [start,end]
};
function startPos(nums, target){
    const n=nums.length
    let left=0
    let right=n-1
    while(left<=right){
        const mid=Math.floor((left+right)/2)//2/4
        if(nums[mid]>=target){
            right=mid-1
        }else{
            left=mid+1
        }
    }
    return left
}

手搓答案(无非废话版)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */

 var searchRange=function(nums,target){
    let n=nums.length,start,end
    function startPos(tar){
        let left=0,right=n-1
        while(left<=right){
            let mid=((right-left)>>1)+left
            if(nums[mid]<tar){
                left=mid+1
            }else{
                right=mid-1
            }
        }
        return left
    }
    start=startPos(target)
    end=startPos(target+1)-1
    if(nums[start]!=target) return [-1,-1]
    return [start,end]
 }

总结

 注意while(left<=right)这里要判断=的情况也要循环一次

 33. 搜索旋转排序数组

题目链接:33. 搜索旋转排序数组

难度:中等

刷题状态:2刷

新知识:

解题过程

思考

示例 1:

输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
题解分析

参考题解链接:搜索旋转排序数组

放下1刷过程

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    //[4,5,6,7,0,1,2]   5
    //[5,6,7,0,1,2,4]   5
    const n=nums.length
    let min=Math.min(...nums)
    let max=Math.max(...nums)
    let left=0
    let right=n-1
    let res=-1
    if(nums[left]==target){
        return 0
    }
    if(nums[right]==target){
        return n-1
    }
    if(n==1){
        return nums[0]==target?0:-1
    }
    while(left+1<right){
        let mid=((right-left)>>1)+left
        // console.log('mid',mid)
        //nums[0]  target nums[mid] max  左边,right=mid
        //nums[0]  nums[mid] target max  左边,left=mid
        //min  target nums[mid] nums[n-1]  右边,right=mid
        //min  nums[mid] target nums[n-1]  右边,left=mid

        //nums[0]  target max    min nums[mid] nums[n-1]  两边,right=mid
        //nums[0]  nums[mid] max    min target nums[n-1]  两边,left=mid
        let targetLr=(nums[0]<=target)&&(target<=nums[mid])&&(nums[0]<=max)
        let targetLl=(nums[0]<=nums[mid])&&(nums[mid]<=target)&&(target<=max)
        let targetRr=(min<=target)&&(target<=nums[mid])&&(nums[mid]<=nums[n-1])
        let targetRl=(min<=nums[mid])&&(nums[mid]<=target)&&(target<=nums[n-1])
        let targetTr=(nums[0]<=target)&&(target<=max)&&(min<=nums[mid])&&(nums[mid]<=nums[n-1])&&(nums[0]!=min)&&(nums[n-1]!=max)
        let targetTl=(nums[0]<=nums[mid])&&(nums[mid]<=max)&&(min<=target)&&(target<=nums[n-1])&&(nums[0]!=min)&&(nums[n-1]!=max)
        // console.log(targetLr,targetLl,targetRr,targetRl,targetTr,targetTl)
        if(nums[mid]==target){
            res=mid
            break
        }else if(targetLr||targetRr||targetTr){
            right=mid
        }else if(targetLl||targetRl||targetTl){
            left=mid
        }else{
            break
        }
        // console.log('left',left)
        // console.log('right',right)
    }
    return res
};

手搓答案(无非废话版)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */

 var search=function(nums,target){
    let n=nums.length
    if(n==0) return -1
    if(n==1) return nums[0]==target?0:-1
    let left=0,right=n-1
    while(left<=right){
        //console.log(left,right)
        let mid=((right-left)>>1)+left
        if(nums[mid]==target) return mid
        if(nums[0]<=nums[mid]){
            if(nums[0]<=target&&target<=nums[mid]){
                right=mid-1
            }else{
                left=mid+1
            }
        }else{
            if(nums[mid]<=target&&target<=nums[n-1]){
                left=mid+1
            }else{
                right=mid-1
            }
        }
    }
    return -1
 }

总结

 应该用手搓答案里面的,保证时间复杂度为 O(log n)

 ​​​​​​​​​​​​​​​​​​​​​153. 寻找旋转排序数组中的最小值

题目链接:​​​​​​​153. 寻找旋转排序数组中的最小值

难度:中等

刷题状态:2刷

新知识:

解题过程

思考

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
题解分析

参考题解链接:​​​​​​​和最后一个数比大小,简洁二分(Python/Java/C++/C/Go/JS/Rust)

放下1刷过程

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {
    //[3,4,5,1,2]
    //[4,5,1,2,3]
    const n=nums.length
    let left=-1
    let right=n-1//4
    while(left+1<right){
        let mid=((right-left)>>1)+left//2
        if(nums[mid]>nums[n-1]){
            left=mid
        }else{
            right=mid
        }
        // console.log('nums[left]',nums[left])
        // console.log('nums[right]',nums[right])
    }
    return nums[right]
    // return Math.min(...nums)
};

手搓答案(无非废话版)

/**
 * @param {number[]} nums
 * @return {number}
 */

 var findMin=function(nums){
    let n=nums.length,res=nums[0]
    let left=0,right=n-1
    while(left<=right){
        let mid=((right-left)>>1)+left
        if(nums[mid]>nums[n-1]){
            left=mid+1
        }else{
            right=mid-1
        }
    }
    return nums[left]
 }

总结

 拿下

 ​​​​​​​​​​​​​​4. 寻找两个正序数组的中位数

题目链接:​​​​​​​​​​​​​​4. 寻找两个正序数组的中位数

难度:困难

刷题状态:1刷

新知识:

解题过程

思考

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

想不出来,直接看答案

题解分析

参考题解链接:​​​​​​​​​​​​​​详细通俗的思路分析,多解法

详细分析如下

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
    let m=nums1.length,n=nums2.length,A=nums1,B=nums2
    if(m>n) return findMedianSortedArrays(B,A)

    //初始化二分查找的边界
    let imin=0,imax=m
    while(imin<=imax){
        //计算当前的分割点i j
        //i 是在数组 A 中的分割点索引。它表示在数组 A 中,有 i 个元素位于左半部分,剩下的 m - i 个元素位于右半部分(其中 m 是数组 A 的长度)。j同理
        let i=Math.floor((imin+imax)/2)
//  i + j = m - i  + n - j  + 1也就是 j = ( m + n + 1) / 2 - i
        let j=Math.floor((m+n+1)/2)-i

        //检查分割是否有效,如果B[j-1]>A[i],说明要增大i
        if(j&&i!=m&&B[j-1]>A[i]){imin=i+1} 

        //如果A[i-1]>B[j],说明要减小i
        else if(i&&j!=n&&A[i-1]>B[j]){imax=i-1} 

        //分割有效,处理边界条件
        else{
            let macLeft=0
            //左半部分最大值在B[j-1]
            if(i==0){maxLeft=B[j-1]} 
            //左半部分最大值在A[i-1]
            else if(j==0){maxLeft=A[i-1]}
            //否则,左半部分的最大值是A[i-1],B[j-1]的较大值
            else{maxLeft=Math.max(A[i-1],B[j-1])}

            //奇数,返回maxLeft
            if((m+n)%2==1) return maxLeft

            //偶数
            let minRight=0
            //右半部分最小值在B[j]
            if(i==m) {minRight=B[j]}
            //右半部分最小值在A[i]
            else if(j==n) {minRight=A[i]}
            //否则,右半部分最大值是A[i],B[j]的较小值
            else{minRight=Math.min(A[i],B[j])}

            return (maxLeft+minRight)/2.0
        }
    }
};

手搓答案(无非废话版)

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */

 var findMedianSortedArrays=function(nums1,nums2){
    let m=nums1.length,n=nums2.length,A=nums1,B=nums2
    if(m>n) return findMedianSortedArrays(nums2,nums1)
    let imin=0,imax=m
    while(imin<=imax){
        let i=Math.floor((imin+imax)/2)
        let j=Math.floor((m+n+1)/2)-i

        if(j&&i!=m&&B[j-1]>A[i]) {imin=i+1}
        else if(i&&j!=n&&A[i-1]>B[j]) {imax=i-1}
        else{
            let maxLeft=0
            if(i==0){maxLeft=B[j-1]}
            else if(j==0){maxLeft=A[i-1]}
            else{maxLeft=Math.max(A[i-1],B[j-1])}

            if((m+n)%2==1) return maxLeft

            let minRight=0
            if(i==m) {minRight=B[j]}
            else if(j==n) {minRight=A[i]}
            else{minRight=Math.min(A[i],B[j])}
            return (maxLeft+minRight)/2.0
        }
    }
 }

总结

不好理解,其实有更简单的方法,但这种方法是字节笔试考过的

 ​​​​​​​​​​​​​​20. 有效的括号

题目链接:​​​​​​​​​​​​​​​​​​​​​20. 有效的括号

难度:简单

刷题状态:1刷

新知识:

解题过程

思考

示例 1:

输入:s = "()"

输出:true

用数组模拟栈

括号必须以正确的顺序闭合:这意味着括号不能交叉匹配。例如,([)] 是无效的

题解分析

参考题解链接:​​​​​​​​​​​​​​有效的括号

详细分析如下

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    let n=s.length,arr=[]
    if(n%2==1) return false
    for(let i=0;i<n;i++){
        if(s[i]=='(') arr.push(')')
        else if(s[i]=='{') arr.push('}')
        else if(s[i]=='[') arr.push(']')
        //核心思想
        //用数组来模拟栈的表达方式
        else if(arr.length==0||arr[arr.length-1]!=s[i]){return false}
        else{
            arr.pop()
        }
    }
    //如果arr没pop完,说明不符合
    return arr.length==0
};

手搓答案(无非废话版)

/**
 * @param {string} s
 * @return {boolean}
 */
 var isValid=function(s){
    let n=s.length,arr=[]
    for(let i=0;i<n;i++){
        let c=s[i]
        if(c=='(') {arr.push(')')}
        else if(c=='{') {arr.push('}')}
        else if(c=='[') {arr.push(']')}
        else if(arr.length==0||arr[arr.length-1]!=c){return false}
        else{ arr.pop()}
    }
    return arr.length==0
 }

总结

拿下

相关文章:

  • 论文写作篇#7:YOLO论文中的全称和缩写,什么时候全称什么时候缩写,全称和缩写谁在括号里?
  • 约束文件SDC常用命令
  • 【Go】数组
  • 中间件监控:保障应用稳定性和响应速度
  • Servlet中request、response、session 用法
  • C++学习笔记(二十五)——vector
  • OpenCV第2课 OpenCV的组成结构与图片/视频的加载及展示
  • MapReduce1中资源预先划分为固定数量的map slot和reduce slot,具体是怎么划分的?
  • 深度强化学习(Deep Reinforcement Learning, DRL)
  • java 批量下载doc\excle\pdf
  • leetcode-12.整数转罗马数字
  • git 标签学习笔记
  • Android Monkey测试完全指南:从入门到实战
  • allure结合pytest生成测试报告
  • chrome插件开发之API解析-chrome.tabs.query
  • 【智能搜索引擎技术】第四章搜索引擎索引构建(水课复习自用)
  • Qt在ARM中,如何使用drmModeObjectSetProperty 设置 Plane 的 zpos 值
  • 识别并脱敏上传到deepseek/chatgpt的Word文件中的敏感信息
  • 视频知识库初步设想
  • 游戏摇杆开发:利用 Windows API 实现摇杆输入捕获
  • 白玉兰奖征片综述丨国产剧集创作的此消彼长
  • 证据公布!菲律宾6人非法登上铁线礁活动
  • 五一假期上海推出首批16条“市民健康路线”,这些健康提示请收好
  • 金科服务:大股东博裕资本提出无条件强制性现金要约收购,总代价约17.86亿港元
  • 泽连斯基承认乌情报部门刺杀俄军高官
  • 人社部:就业政策储备充足,将会根据形势变化及时推出