javaScript数组-(进阶算法)-移动零

移动零

给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。
请注意,必须在不复制数组的情况下原地对数组进行操作。

示例1:

输入:nums = [0,1,0,3,12]
输出:[1,3,12,0,0]

示例2:

输入:nums = [0]
输出:[0]

code方式1(遍历优化)

let arr = [0, 1, 0, 3, 12];

function moveZeroes(nums) {
    let len = nums.length;
    let index = 0;
    for(let i = 0; i < len; i++){
        if(nums[i]){
            if(index == i){
                index++
            }else{
                nums[index++] = nums[i];
                nums[i] = 0;
            }
        }
    }
    return nums;
}

console.log(moveZeroes(arr));

解题思路一:

// 定义一个名为moveZeroes的函数,接收一个数组参数nums
function moveZeroes(nums) {

  // 获取输入数组nums的长度
  let len = nums.length;

  // 初始化变量index为0,用于记录非零元素在新数组中的插入位置
  let index = 0;

  // 遍历输入数组nums
  for (let i = 0; i < len; i++) {

    // 检查当前元素是否为非零值
    if (nums[i]) {

      // 情况1:若当前索引等于index,说明非零元素已在正确位置,只需递增index
      if (index == i) {
        index++;
      } 
      
      // 情况2:若当前索引不等于index,需要将非零元素移到index处,并将原位置置零
      else {
        nums[index++] = nums[i]; // 移动非零元素并递增index
        nums[i] = 0;            // 将原位置置零
      }
    }
  }

  // 遍历结束后,返回处理后的数组nums,其中零元素已移动至末尾,非零元素顺序不变
  return nums;
}

code 2 (遍历)

是code1方式的原版,优点(顺势思考,好理解)

let nums = [0,2,0,4,0,6,0,8,0,10]
function moveZeroes(nums) {
  let index = 0;
  for(let i = 0;i<nums.length;i++){
    if(nums[i]!=0){
      nums[index++] = nums[i]
    }
  }
  console.log(index);
  for(let i = index;i<nums.length;i++){
    nums[i] = 0
  }
  return nums;
}
console.log(moveZeroes(nums));

解释

// 定义一个数组nums,包含一系列偶数和零
let nums = [0,2,0,4,0,6,0,8,0,10]

/**
 * 将数组中的所有零移动到末尾
 * @param {Array} nums - 输入的包含数字的数组
 * @return {Array} - 移动零后的数组
 */
function moveZeroes(nums) {
  let index = 0; // 初始化一个索引,用于记录非零元素应该放置的位置

  // 遍历数组,将非零元素依次放到数组的前部
  for(let i = 0;i<nums.length;i++){
    if(nums[i]!=0){
      nums[index++] = nums[i]
    }
  }
  // 将index之后的位置全部填充为零
  for(let i = index;i<nums.length;i++){
    nums[i] = 0
  }
  
  return nums; // 返回移动零后的数组
}

// 打印移动零后的数组
console.log(moveZeroes(nums));

code 3,双指针写法

let nums = [0,2,0,0,4,0,6,0,0,10]
function moveZeroes(nums) {
  let left = 0,right=0;
  while(right<nums.length){
    if(nums[right]!==0){
      [nums[left],nums[right]]=[nums[right],nums[left]]
      left++
    }
    right++
  }

  return nums
}
console.log(moveZeroes(nums));

代码解释

// 定义一个数组nums,其中包含一系列偶数和零
let nums = [0,2,0,4,0,6,0,8,0,10];
/**
 * 将数组中所有的零移动到末尾
 * @param {Array} nums - 输入的包含数字的数组
 * @return {Array} - 移动零后的数组
 */
function moveZeroes(nums) {
  let left = 0, right = 0; // 初始化左右指针,left指向非零元素应放置位置,right用于遍历数组

  // 使用双指针法遍历数组,当遇到非零元素时与left所指位置交换
  while (right < nums.length) {
    if (nums[right] !== 0) {
      [nums[left], nums[right]] = [nums[right], nums[left]]; // 交换left与right位置的元素
      left++; // 左指针向右移动,准备处理下一个非零元素
    }
    right++; // 右指针继续向右移动,遍历下一个数组元素
  }

  return nums; // 返回移动零后的数组
}

// 打印移动零后的数组
console.log(moveZeroes(nums));
var moveZeroes = function(nums) {
  nums.sort((a, b) => b ? 0 : -1);
};

Code4 (学习)


这段代码定义了一个名为 moveZeroes 的 JavaScript 函数,其作用是将给定数组 nums 中的所有零元素移动到数组的末尾。该函数实现方式非常简短,使用了数组的 sort() 方法并传入一个自定义的比较函数作为参数。以下是详细的解释:

var moveZeroes = function(nums) {
  nums.sort((a, b) => b ? 0 : -1);
};
  1. 声明函数:
  • var moveZeroes = function(nums) 定义了一个名为 moveZeroes 的变量,并将其赋值为一个匿名函数。这个函数接受一个参数 nums,即待处理的数组。
  1. 使用 sort() 方法:
  • 函数体内部仅有一行代码:nums.sort((a, b) => b ? 0 : -1);
  • sort() 是 JavaScript 数组的一个原生方法,用于对数组元素进行排序。它通常接受一个可选的比较函数作为参数,该函数定义了元素之间如何进行比较以确定它们的相对顺序。详细用法可参考《javascript深度理解数组的sort()排序》
  1. 自定义比较函数:
  • (a, b) => b ? 0 : -1 是一个箭头函数,用于作为sort()方法的比较函数。它接收两个参数a b,分别代表正在比较的数组元素。
  • 这个箭头函数的逻辑如下:
    b ? 0 : -1 使用了三元运算符。如果条件 b 为真(非零),则返回 0;否则返回 -1
    b 非零(即 b 是一个非零数值)时,比较函数返回 0,表示 a 和 b 相等,sort() 方法不会改变它们的相对顺序。
    b 为零时,比较函数返回 -1,表示 a 应该排在 b 之前。由于 sort() 默认为升序排列,返回-1会将 a 向数组的头部移动,而 b(零值)则向后移。

综上所述,这段代码通过利用 sort() 方法及自定义比较函数,实现了将数组 nums 中的所有零元素向数组末尾移动的效果。尽管这种实现方式简洁,但需要注意的是,它依赖于sort()方法的稳定性(即相等元素的原始顺序保持不变),且对于大型数组可能会有性能上的考量,因为 sort() 方法通常采用一种通用排序算法(如快速排序、归并排序等),其时间复杂度为 O(n log n),并不适合于简单地移动特定元素的任务。在实际应用中,使用上面的双指针法或其他更直接的遍历交换方法可能更为高效。

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

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

相关文章

ObjectMapper的具体介绍与使用

文章目录 声明一、前言二、ObjectMapper与JSONObject比较1、核心主要有三个部分&#xff1a;依赖包不同 2、ObjectMapper使用概述2.1、工程的pom.xml导包信息2.2、创建案例中的测试对象2.3、对象和JSON相互转化2.3.1、测试代码2.3.2、测试结果展示 2.4、集合和JSON像话转化2.4.…

【让自己的U盘变得与众不同】

文章目录 今日座右铭&#xff1a;在心里种花&#xff0c;人生才不会荒芜。 文章目录 文章目录前言一、准备ICO图标二、插入U盘1.点击新建文本文档-输入代码-点击保存2.将代码文本文档名称修改为autorun.inf在这里插入图片描述3.将图标及代码文本文档放入U盘中在这里插入图片描述…

深度残差收缩网络中,使用 Sigmoid 函数的用意在哪?

在深度残差收缩网络中&#xff0c;使用 Sigmoid 函数将输出归一化到 0 和 1 之间的目的是为了限制输出值的范围&#xff0c;并且使得输出可以被解释为概率。这个 Sigmoid 函数的输出可以被看作是一个置信度或者概率的度量&#xff0c;表示某个事件发生的可能性。 在设置阈值时…

财富池指标--通达信主力建仓免费指标公式源码

主力交易一只个股&#xff0c;一般会经过以下几个阶段&#xff1a;建仓、拉升、出货。那么&#xff0c;怎么判断一只股票正处于主力建仓时期呢&#xff1f; 1、从k线图上来看 个股走势图中&#xff0c;连续出现小阳线的k线图&#xff0c;其成交量持续放量&#xff0c;或者在个…

【学习笔记】rt-thread

任务 创建好任务&#xff0c;不管是动态还是静态创建&#xff0c;任务的状态是init &#xff0c;通过start方法来启动任务&#xff1b;线程大小 设置小了&#xff0c;无法正常工作&#xff1f;显示占空间100% 启动过程 TODO 这是编译器特性&#xff1f; 因为RT-Thread使用编…

【QT+QGIS跨平台编译】181:【QGIS+Qt跨平台编译】—【错误处理:找不到_DEBUGA】

点击查看专栏目录 文章目录 一、找不到_DEBUGA二、原因分析三、错误处理 一、找不到_DEBUGA 报错信息&#xff1a; 二、原因分析 采用了非UNICODE&#xff1a; DEFINES - UNICODE没法识别 _DEBUGA 但可以识别 _DEBUG 三、错误处理 修改 _DEBUGA 为 _DEBUG

Android13 开机时间优化

前言 实际生活当中&#xff0c;针对某些应用场景&#xff0c;对Android启动时间要求比较严格&#xff0c;比如车载&#xff0c;车都开出去几公里了&#xff0c;IVI系统还没起来&#xff0c;这就比较尴尬&#xff0c;所以&#xff0c;优化Android启动时间是一项非常重要的工作。…

windows Nginx上部署若依后台管理登录界面之验证码不显示

大多数情况都是本地电脑Nginx部署正常&#xff0c;服务器Nginx部署验证码不显示。如下图 其实是Nginx配置有问题 server {listen 80;//监听端口server_name 域名或者公网ip等;location / {root D:/dist;//前端包文件路径需要修改index index.html; //不用管try_files …

k8s的service为什么不能ping通?——所有的service都不能ping通吗

点击阅读原文 前提&#xff1a;kube-proxy使用iptables模式 Q service能不能ping通&#xff1f; A: 不能&#xff0c;因为k8s的service禁止了icmp协议 B: 不能&#xff0c;因为clusterIP是一个虚拟IP&#xff0c;只是用于配置netfilter规则&#xff0c;不会实际绑定设备&…

深入理解 C++ 中的 KeyFrame 和 KeyFrame*:对象与指针的选择与管理

本文详细讨论了在 C 编程中 KeyFrame 类及其指针 KeyFrame* 的用法、区别与联系。通过探索两者的内存管理、生命周期及使用场景&#xff0c;本文旨在帮助开发者更好地理解何时以及如何选择使用对象或指针&#xff0c;从而提高代码的效率和安全性。 在 C 中&#xff0c;KeyFrame…

求1000以内正整数的平方根(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>int main() {//初始化变量值&#xff1b;int number 0;int result 0;//提示用户&#xff1b;printf("请输入1000以内求平方根的…

Python 版分布式消息队列 Kafka 实现图片数据传输

1、Kafka 介绍 在使用 Kafka 之前&#xff0c;通常需要先安装和配置 ZooKeeper。ZooKeeper 是 Kafka 的依赖项之一&#xff0c;它用于协调和管理 Kafka 集群的状态。 ZooKeeper 是一个开源的分布式协调服务&#xff0c;它提供了可靠的数据存储和协调机制&#xff0c;用于协调…

超越GPT-4V!马斯克发布Grok-1.5 With Vision

在 Grok-1 开源后不到一个月&#xff0c;xAI 的首个多模态模型就问世了。Grok-1.5V是XAI的第一代多模态模型&#xff0c;除了其强大的文本处理能力之外&#xff0c;Grok现在还能够处理包括文档、图表、图形、屏幕截图和照片在内的各种视觉信息。相信Grok-1.5V将很快提供给现有的…

基于ssm的社区再就业培训管理系统的设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本社区再就业培训管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…

【Spring】依赖注入(DI)时常用的注解@Autowired和@Value

目录 1、Autowired 自动装配 1.1、要实现自动装配不是一定要使用Autowired 1.2、Autowired的特性 &#xff08;1&#xff09;首先会根据类型去spring容器中找(bytype),如果有多个类型&#xff0c;会根据名字再去spring容器中找(byname) &#xff08;2&#xff09;如果根据名…

Sony Camera Remote SDK在Windows上的使用

Sony官方提供了相机遥控软件开发包&#xff0c;允许用户自行开发应用软件&#xff0c;实现对相机的远程控制&#xff0c;包括拍摄、监看和文件传输等。截至目前最新的版本是2024.4.12发布的1.12.00版本&#xff0c;下载链接如下&#xff1a;Camera Remote SDK | LICENSE AGREEM…

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中&#xff0c;温湿度传感器&#xff08;DHT11&#xff09;以及光照强度传感器&#xff08;BH1750&#xff09;往往是必不可少的两个外设&#xff0c;下面我们来剖析这两个外设的原理&#xff0c;以及使用。 1. 温湿度传感…

elasticsearch 下载、启动和账号密码登录

因为我的电脑是 window&#xff0c;以下都是以 window 环境举例。 一、下载 Elasticsearch 是使用 java 开发的&#xff0c;且 7.8 版本的 ES 需要 JDK 版本 1.8 以上&#xff0c;安装前注意java环境的准备。 官网地址&#xff1a;https://www.elastic.co/cn/ 下载地址&#xf…

云安全与网络安全:有什么区别?

云计算已经存在了一段时间&#xff0c;但某些术语的正确含义仍然存在混乱。一个例子是区分云安全与网络安全。 首先&#xff0c;让我们看一下网络安全一词 &#xff0c;以了解它的含义。然后&#xff0c;我们将将该术语与云安全进行比较&#xff0c;以了解两者在几个关键领域的…

OpenHarmony实战开发-如何使用AKI轻松实现跨语言调用。

介绍 针对JS与C/C跨语言访问场景&#xff0c;NAPI使用比较繁琐。而AKI提供了极简语法糖使用方式&#xff0c;一行代码完成JS与C/C的无障碍跨语言互调&#xff0c;使用方便。本示例将介绍使用AKI编写C跨线程调用JS函数场景。通过调用C全局函数&#xff0c;创建子线程来调用JS函…
最新文章