leetcode刷题之数组问题总结,二分法,移除元素,滑动窗口相关问题,螺旋矩阵相关问题

news2025/4/5 0:37:30

目录

    • 一、二分查找相关应用
      • 704.二分查找
      • 35.搜索插入位置
        • 方法一:二分法
        • 暴力解法
      • 34.在排序数组中查找元素的开始位置和最后一个位置
        • 方法一:暴力解法
        • 方法二:二分法,确定左右两侧的边界
      • 69.x的平方根
        • 方法一:二分法
        • 方法二:暴力解法
        • 错解:多次判断,超时了
      • 367.有效完全平方数
        • 方法一:暴力解法
        • 方法二:二分法
    • 二、移除元素相关
      • 27.移除元素
        • 方法一:暴力解法
        • 暴力解法2
        • 快慢指针方法
        • 双向指针
      • 26.删除有序数组中的重复项
        • 暴力解法
        • 快慢指针
      • 283.移动零
        • 错解
        • 快慢指针
        • 暴力解法
      • 844.比较含退格的字符串
        • 方法一:使用栈 栈是用来解决括号匹配等问题的一大利器
        • 方法二:使用指针,从右往左
      • 977.有序数组的平方
        • 方法一:暴力解法
        • 方法二:双指针
    • 三、滑动窗口相关问题
      • 209.长度最小的子数组
        • 方法一:暴力解法
        • 暴力解法修改
        • 滑动窗口 最小滑动窗口
      • 904.水果成篮
        • 暴力解法
        • 滑动窗口 这里是最大滑动窗口
      • 76.最小覆盖子串
    • 三、螺旋矩阵相关问题
      • 54.螺旋矩阵
        • 方法一:一圈一圈的push
        • 方法二:螺旋push到底
        • 方法二判断条件的修改
      • 59.螺旋矩阵2
        • 方法一:一圈一圈的加
        • 直接一圈到底

一、二分查找相关应用

704.二分查找

在这里插入图片描述

var search = function(nums, target) {
    let low = 0,high = nums.length - 1
    let mid = Math.ceil(low + (high - low) /2)
    while(low<=high){
        mid = Math.ceil(low + (high - low) /2)
        if(target==nums[mid]){
            return mid
        }else if(nums[mid]<target){
            //往右走
            low = mid + 1
        }else{
            //往左走
            high = mid - 1
        }
    }
    return -1
};

35.搜索插入位置

在这里插入图片描述

方法一:二分法

var searchInsert = function(nums, target) {
    //二分查找 找到该插入到的位置
    let low = 0,high = nums.length - 1
    let mid = 0
    while(low<=high){
        mid = Math.ceil(low + (high - low)/2)
        if(nums[mid]==target){
            return mid
        }else if(target<nums[mid]){
            //往左走
            high = mid - 1
        }else{
            //往右走
            low = mid + 1
        }
    }
    //当low==high的时候,mid = low = high 还未找到target,if(target<nums[mid]) => high = mid - 1,这时候mid左侧都比target小 故target应该放到mid的位置,if(target>nums[mid]) => low = mid + 1,包括mid和他左侧的都比他小,target应该放入到mid+1的位置 总之返回位置总是high + 1
    return nums[mid]>target?mid:mid+1
};

暴力解法

var searchInsert = function(nums, target) {
    //暴力解法
    let len = nums.length
    for(let i = 0;i<len;i++){
        if(nums[i]==target){
            //找到target了
            return i
        }else if(nums[i]>target){
            //将target放入到nums[i]
            return i
        }
    }
    return len

};

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

在这里插入图片描述

方法一:暴力解法

var searchRange = function(nums, target) {
    if(nums==[]) return [-1,-1]
    let start = null,end = null
    for(let i=0;i<nums.length;i++){
        if(nums[i]==target){
            start = i
            break //结束循环
        }
    }
    //倒着来 去找target
    for(let j = nums.length - 1;j>=0;j--){
        if(nums[j]==target){
            end = j
            break
        }
    }
    if(start==null&&end==null){
        return [-1,-1]
    }
    return [start,end]
};

方法二:二分法,确定左右两侧的边界

var searchRange = function(nums, target) {
    //由于数组是递增的 那么如果target有多个的话,一定是相邻的 可以使用二分法来分别找到左右边界
    const getLeftBorder = (nums,target) =>{
        let low = 0,high = nums.length - 1
        let mid = Math.ceil((low+high)/2) //找到中间的下标
        let leftBorder = null//用来记录左边界
        while(low<=high){
            mid = Math.ceil((low+high)/2)
            if(nums[mid]>=target){
                //注意 这里等于的时候也要移动
                high = mid - 1
                leftBorder = high
            }else{
                low = mid + 1
            }
        }
        return leftBorder   //根据循环里面的判断条件,最后跳出循环的时候,high位于范围的左侧
    }

    const getRightBorder = (nums,target) =>{
        let low = 0,high = nums.length - 1
        let mid = Math.ceil((low+high)/2) //找到中间的下标
        let rightBorder = null
        while(low<=high){
            mid = Math.ceil((low+high)/2)
            if(nums[mid]<=target){ //这样才能移动到右侧边界
                low = mid + 1
                rightBorder = low
            }else{
                high = mid - 1
            }
        }
        return rightBorder 
    }

    const left = getLeftBorder(nums,target)
    const right = getRightBorder(nums,target)
    //情况一:nums为空 或者 target不再这个范围内
    if(nums==[]||left==null||right==null){
        return [-1,-1]
    }
    //要保证left与right之间有一个结点
    if(right-left>1){
        return [left+1,right-1]
    } 
    return [-1,-1]
    
};

69.x的平方根

在这里插入图片描述

方法一:二分法

var mySqrt = function(x) {
    //计算并返回x的算术平方根 这里给出的是非负整数
    //除了0之外 别的非负整数的算术平方根的范围是1 到 x
    //里用二分法 从 1 到 x 之间进行判断
    let low = 1,high = x
    let mid = null
    while(low<=high){
        mid = Math.ceil((low+high)/2)
        if(mid*mid<=x){
            if((mid+1)*(mid+1)>x){
                return mid
            }
            low = mid + 1
        }else{
            if((mid-1)*(mid-1)<=x){
                return mid - 1
            }
            high = mid - 1
        }
    }
    //如果在x = 0 那么返回0
    return 0
};

方法二:暴力解法

var mySqrt = function(x) {
    if(x==0) return 0 
    //如果x = 1 那么这个遍历中只有一项 没有i+1 就会出错
    if(x==1) return 1
    for(let i=1;i<x;i++){
        if(i*i<=x&&(i+1)*(i+1)>x){
            return i
        }
    }
};

错解:多次判断,超时了

var mySqrt = function(x) {
    //计算并返回x的算术平方根 这里给出的是非负整数
    //除了0之外 别的非负整数的算术平方根的范围是1 到 x
    //里用二分法 从 1 到 x 之间进行判断
    
    let low = 1,high = x
    let mid = null
    while(low<=high){
        mid = Math.ceil((low+high)/2)
        if(mid*mid<=x&&(mid+1)*(mid+1)>x){
            return mid
        }
        if(mid*mid<x&&(mid+1)*(mid+1)<x){
            //继续往右侧移动
            low = mid + 1
            continue
        }
        if(mid*mid>x&&(mid-1)*(mid-1)<=x){
            return mid - 1
        }
        if(mid*mid>x&&(mid-1)*(mid-1)>x){
            //想左侧移动
            high = mid - 1
            continue
        }
    }
    //如果在x = 0 那么返回0
    return 0
};

367.有效完全平方数

在这里插入图片描述

方法一:暴力解法

var isPerfectSquare = function(num) {
    //正整数num 那么它的平方根一定在 1 到 num之间    这里注意1的平方还是1
    for(let i = 1;i<=num;i++){
        if(i*i==num){
            return true
        }
    }
    return false
};

方法二:二分法

var isPerfectSquare = function(num) {
    //二分法 num的平方根一定在 1 到num之间
    if(num==1) return true
    let low = 1,high = num
    while(low<=high){
        mid = Math.ceil((low+high)/2)
        if(mid*mid==num){
            return true
        }else if(mid*mid<num){
            //要往右走
            low = mid + 1
        }else{
            //往左走
            high = mid - 1
        }
    }
    //未找到
    return false
};

二、移除元素相关

27.移除元素

在这里插入图片描述

方法一:暴力解法

var removeElement = function(nums, val) {
    //题目说了 数组的顺序可以改变
    //对数组进行排序
    nums.sort((a,b)=>a-b)
    //那么val值相同的元素都是相邻的
    let count = 0  //用来记录val的个数
    let start = null  //开始的索引位置

    //找到val的开始位置
    for(let i = 0;i<nums.length;i++){
        if(nums[i]==val){
            start = i
            break//结束循环
        }
    }

    for(let i=0;i<nums.length;i++){
        if(nums[i]==val){
            count++
        }
    }
    nums.splice(start,count)
};

暴力解法2

var removeElement = function(nums, val) {
    //暴力解法二
    let len = nums.length
    //两层for循环 外边的一层是用来找val 里面的for循环用来从后往前移动val
    for(let i=0;i<len;i++){
        if(nums[i]==val){
            //从后往前去移动元素 将当前的nums[i]给替换掉
            for(let j=i;j<len-1;j++){
                nums[j] = nums[j+1]
            }
            //移动元素结束之后 
            len--
            i--//刚刚移动过来的这个元素没有判断,需要判断一下
        }
    }
    return len
};

快慢指针方法

var removeElement = function(nums, val) {
    //快慢指针
    let slow = 0,fast = 0
    //这样就可以只用一个for循环即可
    for(fast;fast<nums.length;fast++){
        if(nums[fast]!==val){    //当遍历到的值不是val时,slow和fast同时移动
            nums[slow++] = nums[fast]  //当遇到的是val,slow会停留在这个val值这里,然后fast向后移动,if fast遇到的这个值不是val,那么slow 和 fast 进行交换 ,else fast遇到的还是val,那么slow还是不动,fast继续移动;由于交换完成之后,slow自动加一,所以最后slow指向数组的末尾的后一个位置
        }
    }
    return slow
};

双向指针

var removeElement = function(nums, val) {
    //从左右两侧进行比较
    let left = 0,right = nums.length - 1
    while(left<=right){
        //左侧指针要找val值
        while(left<=right&&nums[left]!==val){
            ++left
        }
        //右侧指针要找不是val的值
        while(left<=right&&nums[right]==val){
            --right
        }
        //这里曾经有一个错误理解,右侧指针移动的过程中会将等于val的值给忽略过去,最会返回数组长度的时候,要看left 所以这样不会造成影响
        //以上两个while循环结束之后,left指针指向一个等于val的值,right指向一个不等于val的值
        if(left<right){   //if left==right 就没有必要交换了
            nums[left++] = nums[right--]
        }
    }
    //每次结束之后,left都会进行加一,故最后left指向新数组的末尾的下一项
    return left
};

26.删除有序数组中的重复项

暴力解法

var removeDuplicates = function(nums) {
    //暴力解法
    let len = nums.length
    for(let i = 0;i<len;i++){
        let target = nums[i]
        for(let j = i+1;j<len;j++){
            //从这里开始去找target
            if(nums[j]==target){
                //后面的全部数组向前进行移动
                for(let k=j+1;k<len;k++){
                    nums[k-1] = nums[k]
                }
                //移动一次之后,len--
                len--
                j--
            }
        }
    }
    return len
};

快慢指针

var removeDuplicates = function(nums) {
    //千万要注意,nums是升序的  因为是升序的 所以不会出现 3 4 3的情况
    //使用快慢指针
    let slow = 0,fast = 1
    for(fast;fast<nums.length;fast++){
        if(nums[slow]!==nums[fast]){
            slow++
            nums[slow] = nums[fast]
        }
    }
    //因为slow先加一 然后才会将新的值放入到slow这里 故最后结束的时候 slow指向的是数组的最后的位置
    return slow + 1
};

283.移动零

在这里插入图片描述

错解

使用左右两侧指针会导致元素的顺序发生变化

var moveZeroes = function(nums) {
    //使用双指针 左右两侧指针
    let left = 0,right = nums.length - 1
    while(left<=right){
        //左指针去找0
        while(left<=right&&nums[left]!==0){
            ++left
        }
        //右指针将0忽略
        while(left<=right&&nums[right]==0){
            --right
        }
        //执行完成上面两个while循环之后,left指向0 right不指向0 然后将left与right所指向的值进行交换
        if(left<right){
            nums[left] = nums[right]
            nums[right] = 0
        }
    }
};

快慢指针

var moveZeroes = function(nums) {
    //快慢指针 先将非零元素移动到前面 然后再将后面的元素填补为0
    let slow = 0,fast = 0
    for(fast;fast<nums.length;fast++){
        if(nums[fast]!==0){
            nums[slow++] = nums[fast]
        }
    }
    //上面的for循环完成之后,前面都是非零值   此时slow指向非零部分末尾的下一个位置
    for(let i=slow;i<nums.length;i++){
        //将后面全都填充成0
        nums[i] = 0
    }

};

暴力解法

var moveZeroes = function(nums) {
    //暴力解法
    let len = nums.length
    //外层循环判断每一项是否是0 里面的for循环来移动位置
    for(let i=0;i<len;i++){
        if(nums[i]==0){
            for(let j=i+1;j<len;j++){
                nums[j-1] = nums[j]
            }
            len--
            i--
        } 
    }
    let j = len
    while(j<nums.length){
        nums[j] = 0
        j++
    }
};

844.比较含退格的字符串

题目详情
题解参考

方法一:使用栈 栈是用来解决括号匹配等问题的一大利器

var backspaceCompare = function(s, t) {
    //使用栈
    const helper = str =>{
        let stack = []
        for(let i=0;i<str.length;i++){
            if(str.charAt(i)!=='#'){
                stack.push(str.charAt(i))
            }else{
                stack.pop()
            }
        }
        //结束之后,转换成字符串
        return stack.join()
    }
    const str1 = helper(s)
    const str2 = helper(t)
    if(str1==str2){
        return true
    }else{
        return false
    }

};

方法二:使用指针,从右往左

var backspaceCompare = function(s, t) {
    //使用指针
    let i = s.length - 1
    let j = t.length - 1  //指向字符串的最后一个位置
    let skipS = 0
    let skipT = 0   //用来记录从右往左进行遍历过程中遇到的#号
    //主要思路:对两个字符串同时从右侧往左侧进行遍历,如果遇到#,那么skip加一,如果遇到的不是#,且skip是正数,那么skip减一   直到两个字符串都比较完成
    while(i>=0||j>=0){
        //对字符串s进行统计
        while(i>=0){
            if(s[i]=='#'){
                skipS++   //统计遇到的#个数
                i--   //继续往左侧移动
            }else if(skipS>0){
                skipS--   //用来消除前面的字符串
                i--
            }else{
                break
            }
        }
        //对字符串t进行统计
        while(j>=0){
            if(t[j]=='#'){
                skipT++
                j--
            }else if(skipT>0){
                skipT--
                j--
            }else{
                break
            }
        }
        //如果处理退格之后的字符不相等,返回false
        if(s[i]!==t[j]) return false
        i--
        j--
    }
    return true

};

977.有序数组的平方

在这里插入图片描述

方法一:暴力解法

var sortedSquares = function(nums) {
    //方法:先对每个元素进行平方放入到原来的位置,然后对数组进行排序
    for(let i=0;i<nums.length;i++){
        nums[i] = nums[i]*nums[i]
    }
    nums.sort((a,b)=>a-b)
    return nums
};

方法二:双指针

var sortedSquares = function(nums) {
    //思路:由于数组是递增的,数组平方之后的大小 要以 0 为中心,向两侧逐渐变大
    //故只需要数组首尾两端 然后将大的放到新数组的最后一个位置  这里使用双指针,分别指向数组的首尾
    let i = 0, j = nums.length - 1, last = nums.length - 1
    let arr = new Array(nums.length)
    while(i<=j){
        let leftVal = nums[i] * nums[i]
        let rightVal = nums[j] * nums[j]
        arr[last--] = leftVal<rightVal?(j--,rightVal):(i++,leftVal)
    }
    return arr
};

三、滑动窗口相关问题

209.长度最小的子数组

方法一:暴力解法

var minSubArrayLen = function(target, nums) {
    //暴力解法
    let res = [] //用来记录从当前i开始连续有几个元素
    for(let i=0;i<nums.length;i++){
        let sum = nums[i] //用来保存当前的累加和
        if(sum>=target){ //当前值已经满足条件的了,后面就不用再遍历了
            return 1
        }
        for(let j=i+1;j<nums.length;j++){
            sum+=nums[j]
            if(sum>=target){
                res.push(j-i+1)
                break //结束当前的循环
            }
        }
    }
    if(res.length==0) return 0
    //找出res中最小的
    res.sort((a,b)=>a-b)
    return res[0]
};

暴力解法修改

var minSubArrayLen = function(target, nums) {
    //暴力解法
    let min = null //用来记录最小值
    for(let i=0;i<nums.length;i++){
        let sum = nums[i] //用来保存当前的累加和
        if(sum>=target){ //当前值已经满足条件的了,后面就不用再遍历了
            return 1
        }
        for(let j=i+1;j<nums.length;j++){
            sum+=nums[j]
            if(sum>=target){
                min?min = Math.min(min,j-i+1):min = j-i+1
                break //结束当前的循环
            }
        }
    }
    return min?min:0
};

滑动窗口 最小滑动窗口

var minSubArrayLen = function(target, nums) {
    //滑动窗口 i是窗口的最左侧 j是窗口的最右侧
    let res = null //用来记录最小值
    let sum = 0 //用来记录窗口所有元素的和
    let i = 0, j = 0
    for(j;j<nums.length;j++){
        sum+=nums[j]
        while(sum>=target){
            res?res=Math.min(res,j-i+1):res=j-i+1
            //左侧指针i向右侧移动
            sum-=nums[i++]
        }
    }
    return res?res:0
};

904.水果成篮

暴力解法

var totalFruit = function(fruits) {
    //暴力解法
    let max = 0
    //使用两层循环 外层循环是从下标i开始,j是从i往后开始几个
    for(let i=0;i<fruits.length;i++){
        let type1 = null
        let type2 = null
        type1 = fruits[i]
        let sum = 1//当前篮子中的水果数量
        for(let j=i+1;j<fruits.length;j++){
            if(fruits[j]==type1){
                sum++
            }else if(type2==null){
                type2 = fruits[j]
                sum++
            }else if(fruits[j]==type2){
                sum++
            }else{
                break
            }
        }
        max = Math.max(max,sum)
    }
    return max
};

滑动窗口 这里是最大滑动窗口

var totalFruit = function(fruits) {
    let max = 0//用来记录最大值
    let map = new Map() //用来记录某个种类在滑动窗口中出现的次数,注意窗口中只能由两个键值
    let left = 0 //窗口左侧指针
    //下面right是窗口的右侧指针   只要map中只有两个键值,那么窗口就可以一直扩大直到数组结束
    for(let right=0;right<fruits.length;right++){
        //设置键值
        map.set(fruits[right],map.get(fruits[right])+1||1)
        //只要map对象中的键值个数超过两个,那么左侧指针开始往右侧移动
        while(map.size>2){
            map.set(fruits[left],map.get(fruits[left])-1)
            //一直在删除原来窗口中的键的val值,删除过程中,看那两个键 哪个先删除为0 
            if(map.get(fruits[left])==0){
                map.delete(fruits[left])
            }
            //将某个键值给删除之后进行新的窗口 新的窗口中有一个原先的老的键值还有一个新的键值
            ++left
        }
        max = Math.max(max,right-left+1)
    }
    return max
};

76.最小覆盖子串

在这里插入图片描述

var minWindow = function(s, t) {
    //t中也会有重复的元素,但是t不用去重,因为题目中要求要找的字串中必须和t的字符的数量都是一样的
    let map = new Map() //保存t中的所有的字符 及其数量
    for(let i=0;i<t.length;i++){
        map.set(t.charAt(i),map.get(t.charAt(i))+1||1)
    }

    let left = 0, right = 0
    let minStr = ''
    let size = map.size//保存所需要的字符种类
    for(right;right<s.length;right++){
        if(map.has(s[right])){
            map.set(s[right],map.get(s[right])-1)
        }
        if(map.get(s[right])==0) size-- //需求的字符个数减一
        //只有需求的元素都有了,才会执行while
        while(!size){
            let curStr = s.substring(left,right+1)
            minStr?(minStr =  minStr.length<curStr.length?minStr:curStr):minStr = curStr
            if(map.has(s[left])){
                map.set(s[left],map.get(s[left])+1)
                if(map.get(s[left])==1) size++//需求数量加一
            }
           left++
        }
    }
    return minStr

};

三、螺旋矩阵相关问题

54.螺旋矩阵

讲解参考
在这里插入图片描述
思路:最后判断剩余的情况,只能是一行(从左到右,如果是从下到上,那么必然会有一条边从左到右去连接这条从下到上的边,这就成了逆时针了,显然不符合条件)或者是一列(从上到下,也是同理)

方法一:一圈一圈的push

var spiralOrder = function(matrix) {
    //方法一 :按照圈进行遍历 里外都是矩形圈 由于最大的矩形长或者宽不一样 遍历的最里面最后会剩下一列(从上到下) 或者 一行(从左到右)  res:顺时针遍历的
    if(matrix.length==0) return []
    let top = 0, bottom = matrix.length - 1,left = 0, right = matrix[0].length-1
    let res = [] //记录最终结果
    while(top<bottom&&left<right){
        //遍历上层   由于top<bottom left<right所以每一次的遍历都是有头没有尾巴
        for(let i=left;i<right;i++) res.push(matrix[top][i])
        //遍历右侧
        for(let i=top;i<bottom;i++) res.push(matrix[i][right])
        //遍历下侧
        for(let i=right;i>left;i--) res.push(matrix[bottom][i])
        //遍历左侧
        for(let i=bottom;i>top;i--) res.push(matrix[i][left])
        //遍历完一圈之后,向内进行缩圈
        left++
        right--
        top++
        bottom--
    }
    console.log(res)
    //当while循环不满足条件的时候,没有遍历的只有一行或者一列
    //还剩下一行 从左到右
    //这里要注意:下面的循环只能执行一个 当最后只剩下一个节点的时候 下面的两个条件都满足条件 会重复
    if(top==bottom){
        for(let i=left;i<=right;i++){
            res.push(matrix[top][i])
        }
    }else if(left==right){ //只剩下一列
        for(let i=top;i<=bottom;i++){
            res.push(matrix[i][left])
        }
    }
    return res
};

方法二:螺旋push到底

var spiralOrder = function(matrix) {
    if(matrix.length==0) return []
    let res = []
    let left = 0,top = 0,right = matrix[0].length - 1,bottom = matrix.length - 1
    while(left<=right&&top<=bottom){
        for(let i=left;i<=right;i++) res.push(matrix[top][i])
        top++
        for(let i=top;i<=bottom;i++) res.push(matrix[i][right])
        right--
        if(top>bottom||left>right) break
        //遍历下侧
        for(let i=right;i>=left;i--) res.push(matrix[bottom][i])
        bottom--
        //遍历左侧
        for(let i=bottom;i>=top;i--) res.push(matrix[i][left])
        left++
    }
    return res
};

方法二判断条件的修改

var spiralOrder = function(matrix) {
    if(matrix.length==0) return []
    let res = []
    let left = 0,top = 0,right = matrix[0].length - 1,bottom = matrix.length - 1
    let size = matrix.length*matrix[0].length
    while(res.length!==size){
        for(let i=left;i<=right;i++) res.push(matrix[top][i])
        top++
        for(let i=top;i<=bottom;i++) res.push(matrix[i][right])
        right--
        if(res.length==size) break
        //遍历下侧
        for(let i=right;i>=left;i--) res.push(matrix[bottom][i])
        bottom--
        //遍历左侧
        for(let i=bottom;i>=top;i--) res.push(matrix[i][left])
        left++
    }
    return res
};

59.螺旋矩阵2

在这里插入图片描述

方法一:一圈一圈的加

var generateMatrix = function(n) {
    //题目要求构建一个长宽都是n的矩形
    let top = 0,left = 0,bottom = n-1,right = n-1
    let matrix = new Array(n).fill(0).map(item=>item=new Array(n).fill(0))
    let k = 1
    while(left<right&&top<bottom){
        for(let i=left;i<right;i++) matrix[top][i] = k++
        for(let i=top;i<bottom;i++) matrix[i][right] = k++
        for(let i=right;i>left;i--) matrix[bottom][i] = k++
        for(let i=bottom;i>top;i--) matrix[i][left] = k++
        //向内侧走动
        left++
        right--
        top++
        bottom--
    }
    if(left==right){
        for(let i=top;i<=bottom;i++){
            matrix[i][left] = k++
        }
    }else if(top==bottom){
        for(let i=left;i<=right;i++){
            matrix[top][i] = k++
        }
    }
    return matrix
};

直接一圈到底

var generateMatrix = function(n) {
    //一直加到底
    let matrix = new Array(n).fill(0).map(item=>item = new Array(n).fill(0))
    let top = 0,bottom = n-1,left = 0,right = n - 1
    let k = 1
    while(left<=right&&top<=bottom){
        for(let i=left;i<=right;i++) matrix[top][i] = k++
        top++
        for(let i=top;i<=bottom;i++) matrix[i][right] = k++
        right--
        if(top>bottom||left>right) break
        for(let i=right;i>=left;i--) matrix[bottom][i] = k++
        bottom--
        for(let i=bottom;i>=top;i--) matrix[i][left] = k++
        left++
    }
    return matrix
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/562085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图表控件LightningChart JS v.4.0全新发布!引入DataGrid 组件、新的颜色主题

LightningChart JS是性能最高的JavaScript图表库&#xff0c;专注于实时数据可视化。是Web上性能最高的图表库具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用&#xff0c;从而实现高刷新率和流畅的动画。…

MySQL主从同步(不开GTID)

一、背景 了解并熟悉MySQL的主从同步的搭建过程&#xff0c;并解决搭建过程中所碰到的问题。 二、目标 了解并熟悉MySQL的主从同步的搭建过程&#xff0c;并解决搭建过程中所碰到的问题。 IP地址MySQL版本主从关系192.168.3.2445.6.51Master192.168.3.2455.7.41Slaver192.16…

Flutter三棵树系列之详解各种Key | 京东云技术团队

简介 key是widget、element和semanticsNode的唯一标识&#xff0c;同一个parent下的所有element的key不能重复&#xff0c;但是在特定条件下可以在不同parent下使用相同的key&#xff0c;比如page1和page2都可以使用ValueKey(1) 。 常用key的UML关系图如上&#xff0c;整体上…

Apache Hudi 在袋鼠云数据湖平台的设计与实践

在大数据处理中&#xff0c;实时数据分析是一个重要的需求。随着数据量的不断增长&#xff0c;对于实时分析的挑战也在不断加大&#xff0c;传统的批处理方式已经不能满足实时数据处理的需求&#xff0c;需要一种更加高效的技术来解决这个问题。Apache Hudi&#xff08;Hadoop …

安科瑞对于热继电器对电动机保护的探讨

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要:电动机烧毁是每一个生产企业都无法回避的现象&#xff0c;怎样加强电动机保护&#xff0c;使生产工艺系统的稳定&#xff0c;减少企业非正常停机时间。电动机保护成为电气技术人员一个重要课题。因此&#xff0c…

嵌入式 QT QListWidget 显示列表视图的小部件类

目录 1. 添加对象 2. 设置间距 3. 获取内容 4. 删除对象 5.更改对象内容 在Qt框架中&#xff0c;QListWidget是一个用于显示列表视图的小部件类。它提供了一种方便的方式来显示和管理项目列表。QListWidget可以显示文本、图像和其他自定义的项目项&#xff0c;并允许用户进…

Parrot OS 5.3已经发布并可普遍下载

导读Parrot Security近日宣布&#xff0c;Parrot OS 5.3已经发布并可普遍下载&#xff0c;这是这个基于Debian的、面向红客和渗透测试者的、以安全为重点的发行版的最新稳定版本。 Parrot OS 5.3是Parrot OS 5 “Electro Ara “系列的第三部&#xff0c;在Parrot OS 5.2之后两个…

私有化部署即时通讯为什么更安全

即时通讯作为企业沟通工具&#xff0c;在企业的内部沟通和外部交流中发挥着越来越重要的作用。同时&#xff0c;企业即时通讯在提升企业内部效率的同时&#xff0c;也面临着巨大的安全威胁。 根据数据显示&#xff0c;全球有超过4亿人在使用 IM。而其中因用户隐私泄露导致的数据…

十一、数据仓库详细介绍(应用)

这是数据仓库详细介绍的最后一篇&#xff0c;后续还会在补充一些&#xff0c;把遗漏的或者没讲清楚的追加进来。 1. 前言 数据仓库是一种数据管理的方法论&#xff0c;理论概念很早就提出来了&#xff0c;而且各个行业都有广泛深入的应用。因此到目前为止该方法论的理论和实践体…

Taro小程序富文本解析4种方法

1. Taro组件rich-text 优点:使用极其方便,引用一下就行了。缺点:不支持视频,放弃!2. wxParse https://github.com/icindy/wxParse 优点:支持样式,视频缺点:进入页面图片会有由大变正常,太影响了吧。3. taro-parse https://taro-ext.jd.com/plugin/view/5e61f2acb33351…

【Netty】Netty 概述(一)

文章目录 前言一、Java原生API之痛二、Netty的优势2.1 非阻塞 I/O2.2 丰富的协议2.3 异步和事件驱动2.4 精心设计的API2.5 丰富的缓冲实现2.6 高效的网络传输 三、Netty 核心概念3.1 核心组件3.1.1 事件模型3.1.2 字节缓冲区3.1.3 通信API 3.2 传输服务3.2.1 NIO3.2.2 epoll3.2…

让数据背后的那些话创造价值 | 数据增长

从行业背景而言&#xff0c;流量红利逐渐消失&#xff0c;野蛮生长的互联网时代接近尾声。传统的烧钱模式、靠体力投放的形式日渐乏力。但是&#xff0c;企业总是要追求增长的。所以在行业大背景下&#xff0c;依靠技术和数据的力量寻求更科学、更高效的方法达成营销目标&#…

Windows系统数据结构——最小生成树、Prim算法和Kruskal算法

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天总结一下Windows系统数据结构——最小生成树、Prim算法和Kruskal算法。 我在各在论坛看了很多相关帖子&#xff0c;发现一个简单的问题都被复杂化了。最小生成树、Prim算法和Kruskal算法真的没有大家想的…

【JavaSE】Java基础语法(五):数组详解

文章目录 &#x1f378;1.1 数组介绍&#x1f378;1.2 数组的动态初始化1.2.1 什么是动态初始化1.2.2 动态初始化格式&#x1f378;1.3 数组元素访问1.3.1 什么是索引1.3.2 访问数组元素格式1.3.3 示例代码 &#x1f378;1.4 内存分配1.4.1 内存概述1.4.2 java中的内存分配 &am…

Ubuntu crontab 遇到的sh脚本一些问题(手动执行可以,自动执行不行)

问题一&#xff1a; 问题描述&#xff1a; 在写一个脚本循环时候&#xff0c;出现“let:not found”,这是因为在ubuntu默认是指向bin/dash解释器的,dash是阉割版的bash,其功能远没有bash强大和丰富.并且dash不支持let和i等功能. 解决办法&#xff1a; 打开一个终端输入&#xf…

springboot基于Java的校园二手物品交易平台jspm9qw4i

本基于Java的校园二手物品交易平台采用Java语言和Jsp技术&#xff0c;框架采用SPRINGBOOT&#xff0c;搭配Mysql数据库&#xff0c;运行在Idea里。本系统针对校园二手商品的交易而开发&#xff0c;提供管理员、学生、学生二手三种角色的服务。总的功能包括商品的查询、商品的购…

基于html+css的图展示89

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【六袆 - Redis】Redis内存数据库;redis数据结构;redis文档

Redis 关于redis 官方文档&#xff1a; https://redis.io/docs/about/ https://redis.com/redis-enterprise/data-structures/ 关于redis Redis: 是一个开源&#xff08;BSD 许可&#xff09;内存数据结构存储&#xff0c;用作数据库、缓存、消息代理和流引擎。Redis提供数据结…

CNVD - 5000w通用产品的收集方法

本文转载于&#xff1a;https://mp.weixin.qq.com/s?__bizMzg5OTY2NjUxMw&mid2247507214&idx1&sn0e6df46ee930cb35ab0650867cef8af5&chksmc04d5a30f73ad3261a6fa6a8cb8c4ddc4ee8fac2a58f495c05030adc2d27e3ead65264f24f75&mpshare1&scene23&srcid…

MySQL业务并发减数量,数量未减

业务背景 最近在折腾老系统&#xff0c;折腾了好久&#xff0c;发现一个数据库问题&#xff0c;用户点赞数量&#xff0c;如果用户取消点赞情况下&#xff0c;正常情况10次取消数据库都返回成功&#xff0c;但其中有2次没有取消。 数据库场景 在MySQL中看下面一个场景。 业务…