JS代码随想录(一):数组

代码随想录

一、数组理论基础
二、LeetCode 704. 二分查找
三、LeetCode 27. 移除元素
四、LeetCode 977.有序数组的平方
五、LeetCode 209.长度最小的子数组
六、LeetCode 59.螺旋矩阵II
七、数组总结

 一、数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合。

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的

因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

数组的元素是不能删的,只能覆盖。

二、二分查找 (二分法)

题目:. - 力扣(LeetCode) 

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

错解: (未使用二分法)

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

正解:

  • 二分法:
  • 这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件 。
  • 对于位移法和防溢出的理解:
  • right - left:计算两个数的差值。
  • (right - left) >> 1:将差值的二进制表示向右移动一位。这相当于将差值除以2,但因为是位操作,所以通常比整数除法更快。
  • left + ((right - left) >> 1):将上述得到的结果加到 left 上,得到中间值 mid
  • 为什么要这样做而不是直接使用 (left + right) / 2 呢?

    当 left 和 right 都是大整数时,left + right 可能会导致整数溢出。例如,在32位整数系统中,如果 left 是 INT_MAX(即最大的32位整数),而 right 是一个大于零的正数,那么 left + right 就会溢出。而使用位操作可以避免这种情况,因为 right - left 的结果一定是小于或等于 right 的,因此向右移动一位(即除以2)后再加上 left 就不会溢出。

左闭右闭: 

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    // 左闭右闭
    let mid,left=0,right=nums.length-1;
    //right是数组最后一个数的下标, 要加等号是因为,左闭右闭,当l=r时,也包含在寻找的区间
    while(left<=right){
        // // 位运算 + 防止大数溢出
        mid=left+((right-left)>>1);
        // 如果mid所在的数大于目标数,就到左边找,所以right要变
        if(nums[mid]>target){
            right=mid-1;
            // 如果mid所在的数小于目标数,就到右边找,所以left改变
        }else if(nums[mid]<target){
            left=mid+1;
            // 如果刚好等于,就返回mid中位数
        }else{
            return mid;
        }
    }
    return -1;
};

 左闭右开:

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    // 左闭右开
    let mid,left=0,right=nums.length;
    //right是数组最后一个数的下标+1, 不加等号是因为,nums[right]不在查找范围内
    while(left<right){
        // // 位运算 + 防止大数溢出
        mid=left+((right-left)>>1);
        // 如果mid所在的数大于目标数,就到左边找,所以right要变
        if(nums[mid]>target){
            right=mid;
            // 如果mid所在的数小于目标数,就到右边找,所以left改变
        }else if(nums[mid]<target){
            left=mid+1;
            // 如果刚好等于,就返回mid中位数
        }else{
            return mid;
        }
    }
    return -1;
};

三、 移除元素(快慢指针法)

题目:. - 力扣(LeetCode)

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

正确:

  • 数组里面的元素在内存地址中是连续的,是不能删除的,所以要覆盖等于val的值
  • 双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function (nums, val) {
    // 慢指针
    let i = 0;
    // 快指针
    for (j = 0; j < nums.length; j++) {
        // 如果快指针不等于val,就把不等于val的值给i,实现覆盖等于val的值
        if (nums[j] != val) {
            nums[i] = nums[j];
            // 覆盖一次,i加1,最后覆盖的次数就是数组的新长度。
            i++;
        }
    }
    return i;
};

四、有序数组的平方(双指针法)

题目:. - 力扣(LeetCode)

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

 正解:

  • 双指针法:

我们可以从数组的两端向中间遍历,同时比较两端的元素平方后的大小,并将较大的那个平方值添加到结果数组的开头(因为我们是从后向前添加到结果数组的,以保持顺序)。

  • 在JavaScript中,Array.prototype.unshift() 是一个数组方法,用于在数组的开头添加一个或多个元素,并返回新的数组长度。但是,它实际上会修改原始数组,并在其开头添加元素。

在您给出的代码示例中:

  • result.unshift(leftSquare); 会在 result 数组的开头添加 leftSquare 的值。
  • result.unshift(rightSquare); 会在 result 数组的开头添加 rightSquare 的值。
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    const result = [];// 新数组存放
    // left指向开头的指针,right指向数组末尾的指针
    let left = 0, right=nums.length-1;
    // 从两端开始同时计算平方并比较
    while(left<=right){
        const lefts = Math.pow(nums[left], 2);
        const rights = Math.pow(nums[right], 2);
        // 将较大的平方值添加到结果数组的开头
        // 如果lefts大于rights,就把lefts放到新数组最前面
        if(lefts>rights){
            result.unshift(lefts);
            left++
        }else{
            // 反之,就把rights放到新数组最前面
            result.unshift(rights);
            right--;
        }
    }
    return result;
};

五、长度最小的子数组 (滑动窗口)

. - 力扣(LeetCode)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续

子数组

 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

正解:

滑动窗口(双指针) :

滑动窗口

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

var minSubArrayLen = function(target, nums) {
    // 滑动算法
    let left = 0;  
    let sum = 0;  
    // 最小长度为无穷大
    let minLength = Infinity;  
  
    for (let right = 0; right < nums.length; right++) {  
        sum += nums[right];  
  
        // 当窗口内的和大于等于目标值时,移动左指针缩小窗口  
        while (sum >= target) {  
            minLength = Math.min(minLength, right - left + 1);  
            sum -= nums[left];  
            left++;  
        }  
    }  
//  如果找到了,就返回最小子数组的长度;如果没有找到,就返回 0。
// minLength 等于 Infinity就返回0,不等于就返回minLength
    return minLength === Infinity ? 0 : minLength;   
};

六、螺旋矩阵

. - 力扣(LeetCode)

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

正解: 

  1. 初始化矩阵
    首先,需要创建一个大小为 n x n 的矩阵(二维数组),并将所有元素初始化为0或者其他占位符。这个矩阵将用于存放最终的结果。

  2. 设置边界和填充数字
    确定矩阵的四个边界:上边、下边、左边和右边。开始时,上边是矩阵的第一行,下边是最后一行,左边是第一列,右边是最后一列。同时,设置一个变量来跟踪当前要填充的数字,初始值为1。

  3. 按顺时针螺旋填充
    按照“上边 → 右边 → 下边 → 左边”的顺序,依次填充数字。每次填充完一个边后,调整相应的边界,并继续填充下一个边,直到所有格子都被填满。

    • 填充上边:从左到右,填充上边的每个格子,并将上边界下移一行。
    • 填充右边:从上到下,填充右边的每个格子,并将右边界左移一列。
    • 填充下边:在确保下边还有未填充的格子后,从右到左填充下边的每个格子,并将下边界上移一行。
    • 填充左边:在确保左边还有未填充的格子后,从下到上填充左边的每个格子,并将左边界右移一列。
  4. 重复填充过程
    重复步骤3,直到所有的格子都被填满,即当前填充的数字达到 n^2 + 1(因为我们是从1开始填充的,所以当数字大于 n^2 时,说明所有格子已经填满)。

  5. 返回结果
    当所有格子都填满后,返回填充好的矩阵。

这种解题思路的关键在于如何正确地更新边界,并在填充过程中保持顺时针螺旋的顺序。通过不断地缩小边界范围,并依次填充每个边界上的格子,最终可以得到所需的矩阵。

/**
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function(n) {
    // 初始化一个 n x n 的二维数组(矩阵),并用 0 填充所有元素  
    let matrix = Array(n).fill(0).map(() => Array(n).fill(0));  
  
    // 初始化要填充的数字为 1  
    let num = 1;  
  
    // 定义矩阵的四个边界:上、下、左、右  
    let rowStart = 0, rowEnd = n - 1, colStart = 0, colEnd = n - 1;  
  
    // 当要填充的数字小于等于 n^2 时,继续填充  
    while (num <= n * n) {  
        // 从左到右填充上边界(横向)  
        for (let j = colStart; j <= colEnd; j++) {  
            matrix[rowStart][j] = num++;  
        }  
        // 上边界填充完毕后,上边界下移一行  
        rowStart++;  
  
        // 从上到下填充右边界(纵向)  
        for (let i = rowStart; i <= rowEnd; i++) {  
            matrix[i][colEnd] = num++;  
        }  
        // 右边界填充完毕后,右边界左移一列  
        colEnd--;  
  
        // 从右到左填充下边界(如果还存在未填充的元素)  
        for (let j = colEnd; j >= colStart; j--) {  
            matrix[rowEnd][j] = num++;  
        }  
        // 下边界填充完毕后,下边界上移一行  
        rowEnd--;  
  
        // 从下到上填充左边界(如果还存在未填充的元素)  
        for (let i = rowEnd; i >= rowStart; i--) {  
            matrix[i][colStart] = num++;  
        }  
        // 左边界填充完毕后,左边界右移一列  
        colStart++;  
    }  
  
    // 返回填充好的矩阵  
    return matrix; 
};

七、总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

你真的会用 ChatGPT 吗?来看看这 4 个模式,让你的 AI 技能更上一层楼!(上)

一年半已经过去&#xff0c;ChatGPT 虽然风靡一时&#xff0c;但真正发挥其超过 30% 效能的人却寥寥无几。许多资深用户依然沿用传统的人机交互方式&#xff0c;认为只需要事无巨细地编写指令&#xff0c;让 AI 服从即可。大多数人并不了解这些生成式 AI 的某些不为人之的特性&…

第四百九十八回

文章目录 1. 概念介绍2. 使用方法2.1 固定样式2.2 自定义样式 3. 示例代码4. 内容总结 我们在上一章回中介绍了"GetMaterialApp组件"相关的内容&#xff0c;本章回中将介绍使用get显示SnackBar.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在介…

python自动化办公的代码

以下是一个简单的Python自动化办公代码示例&#xff0c;用于实现一些基本的自动化任务&#xff0c;例如打开文件、读取数据、写入数据和保存文件等。 python import os # 打开文件 def open_file(filename): try: file open(filename, r) data file.read() file.close() ret…

如果你的Google ads账号被暂停了怎么办?

Google Ads账号暂停可能会导致您的企业收入损失。但实际上&#xff0c;除了一些特殊情况外&#xff0c;Google Ads帐户暂停几乎不是永久性的。如果您的帐户已被暂停&#xff0c;有多种方法可以恢复该帐户。 废话不多说&#xff0c;下面为大家分享&#xff01; 一、谷歌广告帐户…

用于视频识别的快慢网络

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;用于视频识别的快慢网络1、文献摘要2、提出方法2.1、SlowFast模型2.2、SlowFast 提出思想 3、相关方法3.1、时空间卷积3.2、基于光…

安卓开发--按键跳转页面

安卓开发--按键跳转页面 前言1. 按键页面跳转1.1 新建布局文件1.2 衔接布局文件&#xff0c;新建Java class类文件1.3 衔接布局文件&#xff0c;修改AndroidManifest.xml文件1.4 调用布局文件1.5 最终效果 前面已经介绍了一个空白按键工程的建立以及响应方式&#xff0c;可以参…

机器学习算法应用——神经网络回归任务、神经网络分类任务

神经网络回归任务&#xff08;4-3&#xff09; 神经网络回归任务&#xff0c;通常指的是使用神经网络模型进行回归分析。回归分析是一种统计学方法&#xff0c;用于研究一个或多个自变量&#xff08;预测变量&#xff09;与一个因变量&#xff08;响应变量&#xff09;之间的关…

python实现动态时钟功能

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 一.前言 时钟,也被称为钟表,是一种用于测量、记录时间的仪器。时钟通常由时针、分针、秒针等计时仪器组成,是现代社会不可或缺的一种计时工具。它的发明和使用极大地改变了人类的生活方式和时间观念。 时钟的类型有很多,…

汇昌联信科技:做拼多多网店要押金吗?

做拼多多网店要押金吗?”这个问题&#xff0c;其实与拼多多的平台规则有关。在开店之前&#xff0c;商家需要详细了解平台的各项规定和费用构成&#xff0c;这样才能做好充足的准备。 一、明确回答问题 做拼多多网店&#xff0c;不需要支付押金。拼多多的入驻门槛相对较低&…

Threejs Shader动态修改Merge合并几何体中单个Mesh的颜色

目录 Merge合并 现象 思路 实现 为单个geometry添加映射 通过id检索Merge后的Geometry映射属性&#xff0c;获取顶点坐标 onBeforeCompile修改编译前材质的着色代码 编译前材质的顶点着色代码 编译前材质的片元着色代码 着色器代码 注意 效果 Merge合并 mergeBuf…

Vue路由拆分

1.在src下建立router&#xff0c;在router中建立文件index 2.将main.js中部分内容复制 App <template> <div><a href"#/friend">朋友</a><br><a href"#/info">信息</a><br><a href"#/music&quo…

数据结构十三:八大排序算法

排序算法&#xff08;sorting algorithm&#xff09;是用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用&#xff0c;因为有序数据通常能够被更高效地查找、分析和处理。排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定&am…

看马斯克与OpenAI的爱恨情仇,AGI之路会走向何方?

揭秘马斯克与OpenAI的决裂&#xff1a;AI的未来将何去何从&#xff1f; ©作者|Steven 来源|神州问学 引言 2024 年 3 月 1 日&#xff0c;时任OpenAI联合创始人的Elon Musk(下文简称&#xff1a;马斯克)将现任 CEO、创始人Sam Altman(下文简称&#xff1a;阿尔特曼)告上…

深度学习设计模式之单例模式

一、单例模式简介 一个类只能有一个实例&#xff0c;提供该实例的全局访问点&#xff1b; 二、单例模式实现步骤 使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。 私有构造函数保证了不能通过构造函数来创建对象实例&#xff0c;只能通过公有静态函数返…

工业机器人应用实践之玻璃涂胶(篇一)

工业机器人 工业机器人&#xff0c;即面向工业领域的机器人。工业机器人是广泛用于工业领域的多关节机械手或多自由度的机器装置&#xff0c;具有一定的自动性&#xff0c;可依靠自身的动力能源和控制能力实现各种工业加工制造功能。工业机器人被广泛应用于电子、物流、化工等…

使用OpenCV实现图像平移

使用OpenCV实现图像平移 程序流程效果代码 程序流程 读取图像并获取其高度、宽度和通道数。定义平移量tx和ty&#xff0c;并创建平移矩阵M。使用cv2.warpAffine函数对图像进行仿射变换&#xff08;平移&#xff09;&#xff0c;得到平移后的图像。显示平移后的图像。等待用户按…

HTML【常用的标签】、CSS【选择器】

day45 HTML 继day44&#xff0c;w3cschool 常用的标签 k) 表格 表格由 table 标签来定义。每个表格均有若干行&#xff08;由 tr 标签定义&#xff09;&#xff0c;每行被分割为若干单元格&#xff08;由 标签定义&#xff09;。字母 td指表格数据&#xff08;table data&…

VSCode:设置顶部文件标签页滚动条的宽度

使用VSCode打开多个文件后&#xff0c;顶部的文件标签可以通过滚动条进行滚动&#xff0c;但是缺点是该滚动条太窄了&#xff0c;不好选择。 可以通过如下方法修改改滚动条的宽度&#xff1a; 1.点击设置 2.选择工作台->编辑管理->Title Scrollbar Sizing->Large 3.可…

QJ71E71-100 三菱Q系列以太网通信模块

QJ71E71-100 三菱Q系列以太网通信模块 QJ71E71-100以太网模块是PLC侧连接Q系列PLC与本站系统的接口模块&#xff0c;如个人计算机和工作站&#xff0c;也是通过以太网使用TCP/IP或UDP/IP通讯协议在 PLC 之间的接口模块。QJ71E71-100外部连接,QJ71E71-100参数规格,QJ71E71-100用…

表面的相似,本质的不同

韩信与韩王信&#xff0c;两个韩信的结局都是被刘邦所杀&#xff0c;似乎结局类似。但是&#xff0c;略加分析&#xff0c;就会发现其中存在本质的区别。 韩信属于必杀。他的王位是要来的&#xff0c;有居功自傲的本意&#xff0c;功高震主而且毫不避讳。而且年轻&#xff0c;…