JavaScript系列——数组元素左右移动N位算法实现

2023-11-19

引言

在自己刚刚毕业不久的时候,去了一家公司面试,面试官现场考了我这道题,我记忆深刻,当时没有想到思路,毫无疑问被面试官当成菜鸟了。
最近刚好在研究数组的各种算法实现,就想到这道题,可以拿来实现一下,纪念自己逝去的青春。

需求

假设有这样一个数组

[1,2,3,4,5]

现在想要左移或者右移N位,比如移动1位

//左移1位
[2,3,4,5,1]

//右移1位
[5,1,2,3,4]

算法实现

这样一道题目,你先不要看我下面的代码,自己思考一下如何实现它,不管是复杂的还是简单的方法。
可以先告诉你我用了2行代码实现左、右移动元素。

拆分法
当我们没有具体思路的时候,就先假设数组移动1位的情况。
[1,2,3,4,5]
=>
[null,1,2,3,4] and [5,null,null,null,null]
=>
[5,1,2,3,4]

这里可以看成2个数组,一个是没有到达边界的元素移动[null,1,2,3,4],一个是到达了边界的元素移动[5,null,null,null,null],当元素到达边界,就会往数组的初始位置移动,形成了一个循环的过程。

很明显,如果我们将这2个移动后的数组合并起来,就是需求的结果。

移动2位

同样符合2个移动后的数组合并起来为结果的情况

[1,2,3,4,5]
=>
[null,null,1,2,3] and [4,5,null,null,null]
=>
[4,5,1,2,3]
刚好移动数组长度
[1,2,3,4,5]
=>
[1,2,3,4,5] and [] //如果没有,就假设为空数组
合并数组

假设移动1位的情况
上面的步骤,我们找到了规律,接下来要做的是找到2个数组,需要用到slice截取数组元素。
截取第一个数组

arr.slice(0,-1)
// [1,2,3,4]

截取第二个数组

arr.slice(-1)
// [5]

合并数组

arr.slice(-1).concat(arr.slice(0,-1))
// [5,1,2,3,4]

这样你就实现了移动1位的情况,接着,你继续拿+5和-5范围内的数字进行测试,发现都可以正常移动,当数字大于5或者小于-5的时候,代码就无效了,始终输出[1,2,3,4,5]

arr.slice(-6).concat(arr.slice(0,-6))
// [1,2,3,4,5]

我们再加上一个小技巧,求余数,假设是移动6,那么,实际上和移动1是相同的,我们就可以根据公式求余数

n = n%arr.length
// n = 6%5 余1

同理,当移动-6时

n = n%arr.length
// n = -6%5 余-1

接着带入公式,发现输出全部都正确了!!

思路分析完了,应该很清晰了吧,源码在下面、

算法源码

arr表示原始数组,n表示移动的距离,可以是正数、可以是0、也可以是负数、正数表示右移,负数表示左移,0表示不移动。

function moveElement(arr, n) {
  if(Math.abs(n)>arr.length) n = n%arr.length
  return arr.slice(-n).concat(arr.slice(0,-n))
}

// moveElement(arr, 9)
// moveElement(arr, 0)
// moveElement(arr, -9)

总结

下次面试要是继续碰到这道题,可能我又当场忘记思路了?

补充

看到有评论讨论不同方案的实现,这些都很厉害,没有唯一的答案,而思考解决方案的时候,要考虑的是时间复杂度,移动数组的元素都会造成数组的重新排列。

第一步方案我觉得应该是找到最小移动位置的代价,即移动2和移动2n是一样的,我们就只需要移动2,不需要再移动n,求余数的作用在于此,根据移动的位置切分出2个数组,不需要移动元素,最后我用的是concat合并2个数组,返回一个新的数组副本,这样就避免了移动元素。

还有一种方案是将2个数组使用new Set(array1)和new Set(array2)设置为集合,集合是key、value的散列表,可以用最少的代价移动位置,不导致重排,用集合移动完之后,再Array.from()转换回数组。

切忌,不要尝试去直接修改原数组的元素位置,这样做代价非常大,尤其是数组长度很长的时候!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript系列——数组元素左右移动N位算法实现 的相关文章

随机推荐

  • 再论人与人的三大关系:生存关系、性关系和经济关系

    黄仁宇在 关系 一文中认为 人类的各种关系之中 以生存的关系 性关系和经济关系最为重要 理想上的工作协作和团队精神 已经不存在 俺做过的几个规模在50人以下的 这说明两个问题 1 小公司的目的不是发展而是不死 然后赚钱 也就是这是一笔买卖而
  • exe4j打包exe_JDK11及以后版本在Win下的打包发布方法

    概述 我在准备使用高版本jdk后 遇到的最麻烦的问题就是打包发布了 主要原因还是jdk的模块化带来的 在经历了长时间折腾后 终于成功完成了这个 当然 只是针对window下的 想要使用高版本jdk打包发布Windows应用 需要准备 exe
  • js中的对象 函数 原型

    关于 Function Object 和 proto prototype 1 每一个对象实例都有一个 proto 属性 这个属性就是指向 对象构造函数的原型 let b new Function console log b proto Fu
  • 【Matlab图片剪裁】

    标题Matlab剪裁图片 提取感兴趣部分 问题描述 当需要从一幅图片中提取一些感兴趣的内容时 比如一些细小的文字 图案等 如果从整个图片中直接提取 必然会大大增加计算量 导致处理时间很长 而且多数计算都是无效计算 进而非常消耗资源 解决办法
  • impala 错误

    问题一 impala state store unrecognized service 原因 当前节点未成功安装impala server impala state store impala catalog 解决方案 yum install
  • Qt生成log日志文件

    摘要 本文在Qt程序中实现了日志功能 读者可以在此基础上进一步创作和拓展 介绍 系统日志一般指存放系统重要运行信息的log txt文件 主要作用有两个 1 记录系统重要的运行信息 2 当系统突然崩溃时 可以根据日志来跟踪和定位程序错误 Qt
  • 常见CAD/CAM控件大全

    前言 CAD CAM 计算机辅助设计与制造 技术是随着计算机和数字化信息技术发展而形成的新技术 是20世纪最杰出的工程成就之一 也是数字化 信息化制造技术的基础 其发展和应用对制造业产生了巨大的影响和推动作用 经过几十年的发展和应用 不仅C
  • Python+Selenium爬虫之动态验证码的处理

    目录 1 拖动下方滑块完成拼图 单独图片 2 拖动下方滑块完成拼图 共同图片 可拖动验证码分为空缺区域为单独的图片和空缺区域与背景图片为一个共同图片 所以实现方式有2种 1 拖动下方滑块完成拼图 单独图片 拖动验证码 实现原理 查看空缺区域
  • [VScode]终端回应“pnpm : 无法将“pnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。“解决思路

    问题概述 遇到问题 在VScode终端输入pnpm install有错误提示 pnpm 无法将 pnpm 项识别为 cmdlet 函数 脚本文件或可运行程序的名称 请检查名称的拼写 如 果包括路径 请确保路径正确 然后再试一次 所在位置 行
  • wps表格中的文字不能顺利水平居中的解决办法

    今天调整别人做的表格 想要把表格中文字水平居中 竟然指令操作后发现很多行的表格无动于衷 发现这样设置一下应该可以解决 WPS文字右边有个小的下拉箭头 选择 格式 段落进行设置 段前段后设置为0 行距设置为单倍行距或者固定行距 固定行距需要测
  • maven私服不能重复部署解决方法

    maven私服不能重复部署解决 1 报错 Return code is 400 ReasonPhrase Repository does not allow updating assets maven releases 2 原因 经排查发现
  • Elasticsearch 7.x生产配置

    虽然Elasticsearch需要很少的配置 但是有一些设置需要手动配置 并且必须在进入生产之前进行配置 1 官方文档 这些重要配置说明 请参考官方文档 https www elastic co guide en elasticsearch
  • c++得到窗口句柄

    include
  • Gitlab Java API 使用示例(亲测、有效)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 简介 一 依赖 常量 Maven依赖 定义常量类 二 增删改查 1 新增私有仓库 2 删除指定仓库 3 修改项目简介和是否开源 三 后续更新 简介 在开发中 偶尔会
  • 算法学习——动态规划的学习

    作者 小 琛 欢迎转载 请标明出处 引言 动态规划是算法中较难的内容 常常被用来区分学习者的档次 笔者也是在面试中发现了这个问题 故而回头认真学习并总结递归算法 希望能够帮助到阅读的你 文章目录 动态规划的思想 动态规划的具体实现步骤 入门
  • QThread介绍

    一 介绍 Qt中的QThread类提供了与平台无关的线程 一个QThread代表了一个在应用程序中可以独立控制的线程 它与进程中的其他线程分享数据 但是是独立执行的 相对于一般的程序都从main 函数开始执行 QThread从run 函数开
  • Q_D指针(d指针)和Q_Q指针(q指针)简介

    文章目录 1 Q D指针 2 Q Q指针 1 Q D指针 在class中配合使用 Q DECLARE PRIVATE 和 Q D 方便获取d指针 d指针指向Class Private 2 Q Q指针 在class Private配合使用 Q
  • 记录--Vue中如何导出excel表格

    这里给大家分享我在网上总结出来的一些知识 希望对大家有所帮助 一 导出静态数据 1 安装 vue json excel npm i vue json excel 注意 此插件对node有版本要求 安装失败检查一下报错是否由于node版本造成
  • hive、impala、prestoDB 优缺点对比

    hive 优点 缺点 被广泛应用 经受时间的考验 既然是基于Mapreduce 也拥有MapReduce所有缺点 包含昂贵的Shuffle操作和磁盘IO操作 运行在Mapreduce框架之上 hive仍然不支持多个reduce操作group
  • JavaScript系列——数组元素左右移动N位算法实现

    引言 在自己刚刚毕业不久的时候 去了一家公司面试 面试官现场考了我这道题 我记忆深刻 当时没有想到思路 毫无疑问被面试官当成菜鸟了 最近刚好在研究数组的各种算法实现 就想到这道题 可以拿来实现一下 纪念自己逝去的青春 需求 假设有这样一个数