js 常见数组算法
数组方法概述
1、不改变原数组,返回新数组
concat()
连接两个或多个数组,两边的原始数组都不会变化,返回被连接数组的一个副本。
join()
把数组中所有元素放入一个字符串中,返回字符串。
slice()
从开始到结束(不包括结束)选择数组的一部分浅拷贝到一个新数组。
map()
创建一个新数组并返回,其中新数组的每个元素由调用原始数组中的每一个元素执行提供的函数得来,原始数组不会改变。
every()
对数组中的每个元素都执行一次指定的回调函数,直到回调函数返回
false
,此时every()
返回false
并不再继续执行。如果回调函数对每个元素都返回true
,那么every()
将返回true
。some()
对数组中的每个元素都执行一次指定的回调函数,直到回调函数返回
true
,此时some()
返回true
并不再继续执行。如果回调函数对每个元素都返回false
,那么some()
将返回false
。
filter()
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
2、改变原数组
forEach()
针对每一个元素执行提供的函数。会修改原来的数组,不会返回执行结果,返回
undefined
。pop()
删除数组最后一个元素,返回被删除的元素。如果数组为空,则不改变数组,返回
undefined
。push()
向数组末尾添加一个或多个元素,返回改变后数组的长度。
reverse()
颠倒数组中元素的位置,返回该数组的引用。
shift()
从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
unshift()
将一个或多个元素添加到数组的开头,并返回新数组的长度。
sort()
对数组的元素进行排序,并返回数组。排序不一定是稳定的。默认排序顺序是根据字符串Unicode码点。
splice()
向数组中添加/删除项目,然后返回被删除项目的新数组。
遍历方法
获取属性名:for..in
和 object.keys()
的区别
for..in
语句:遍历对象的可枚举属性名列表,包括[[Prototype]]原型链。- 对于数组,不仅会包含所有数值索引,还会包含所有可枚举属性。遍历数组使用传统for循环
propertyIsEnumerable(..)
:只检查属性名是否在对象中并且enumerable:true
。Object.keys(..)
:只查找属性名是否在对象中,返回一个数组,包含所有可枚举属性名。Object.getOwnPropertyNames(..)
:只查找属性名是否在对象中,返回一个数组,包含所有属性名,无论是否可枚举。
获取属性值:for..of
和object.values()
for..of
语句:遍历可迭代对象的可枚举属性的值列表,包括[[Prototype]]原型链。object.values()
:返回一个给定对象自身的所有可枚举属性的值的数组,不包括原型链
ES6语法之Map键值对转化数组
new Map创建一个map
- // new Map创建一个map
- let map = new Map([[1,"one"], [2,"two"], [3,"three"]]);
- map.set(4, "four");
- // 获取所有键值对
- console.log("获取key")
- console.log([...map.keys()]) // 输出[1, 2, 3, 4]
- console.log("获取value")
- console.log([...map.values()]) // 输出[one, two, three, four]
- console.log("获取map数组")
- console.log([...map]) // 输出[[1, "one"], [2, "two"], [3, "three"], [4, "four"]]
两个升序数组合并成一个升序数组
- 时间复杂度 O(M+N),空间复杂度O(M+N)
- function merge(left, right){
- let result = [],
- il = 0,
- ir = 0;
- while (il < left.length && ir < right.length) {
- result.push(left[il] < right[ir] ? left[il++] : right[ir++]);
- }
- return result.concat(left.slice(il)).concat(right.slice(ir));
- }
- 时间复杂度 O(M+N) ,空间复杂度 O(1)
- public class Solution {
- // m, n 是数组长度
- public void merge(int[] nums1, int m, int[] nums2, int n) {
- int i = m - 1, j = n - 1, writeIdx = m + n - 1;
- while (i >= 0 && j >= 0)
- nums1[writeIdx--] = nums1[i] > nums2[j]? nums1[i--] : nums2[j--];
- while (j >= 0)
- nums1[writeIdx--] = nums2[j--];
- }
- }
数组去重
- reduce方法
- const distinct = arr => arr.sort().reduce( (init, current) => {
- if (init.length === 0 || init[init.length - 1] !== current) {
- init.push( current );
- }
- return init;
- }, []);
- let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
- distinct(arr); // [1, 2, 3, 4, 5]
- filter方法
- const distinct = arr => arr.filter( (element, index, self) => {
- return self.indexOf( element ) === index;
- });
- let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
- distinct(arr); // [1, 2, 3, 5, 4]
多维数组降维
- const flattenDeep = arr => Array.isArray(arr)
- ? arr.reduce( (a, b) => [...a, ...flattenDeep(b)] , [])
- : [arr]
- flattenDeep([1, [[2], [3, [4]], 5]]); // [1, 2, 3, 4, 5]
两个数组的交集 II
给定两个数组,写一个方法来计算它们的交集。
例如:
给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].
注意:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
跟进:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
- 如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?
解法:
- /**
- * @param {number[]} nums1
- * @param {number[]} nums2
- * @return {number[]}
- */
- var intersect = function(nums1, nums2) {
- var map1 = new Map();
- var number = [];
- for(var i = 0; i < nums1.length; i++) {
- var map1Value = map1.get(nums1[i]);
- map1.set( nums1[i], ( map1Value ? map1Value : 0 ) + 1 );
- }
- for(var i = 0; i < nums2.length; i++) {
- if( map1.has(nums2[i]) && map1.get(nums2[i]) != 0 ) {
- number.push(nums2[i]);
- map1.set( nums2[i], map1.get(nums2[i]) - 1 );
- }
- }
- return number;
- };
从排序数组中删除重复项
- /**
- * @param {number[]} nums
- * @return {number}
- */
- var removeDuplicates = function(nums) {
- if(!nums || nums.length == 0) return 0;
- let len = 0;
- for(let i = 1; i < nums.length; i++) {
- if (nums[len] != nums[i]) {
- nums[++ len] = nums[i];
- }
- }
- return len + 1;
- };
只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素
- /**
- * @param {number[]} nums
- * @return {number}
- */
- var singleNumber = function(nums) {
- let number = 0;
- for(let i = 0; i < nums.length; i++) {
- number ^= nums[i];
- }
- return number;
- };
参考资料:https://blog.csdn.net/qq_35546040/article/details/80284079
两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
- 给定 nums = [2, 7, 11, 15], target = 9
- 因为 nums[0] + nums[1] = 2 + 7 = 9
- 所以返回 [0, 1]
解法:
- /**
- * @param {number[]} nums
- * @param {number} target
- * @return {number[]}
- */
- var twoSum = function(nums, target) {
- var map = new Map();
- var number = [];
- for(var i = 0; i < nums.length; i ++) {
- if(map.has(target - nums[i])) {
- number.push(i, map.get(target - nums[i]));
- break;
- }
- map.set(nums[i], i);
- }
- return number;
- };
旋转数组
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
- 输入: [1,2,3,4,5,6,7] 和 k = 3
- 输出: [5,6,7,1,2,3,4]
- 解释:
- 向右旋转 1 步: [7,1,2,3,4,5,6]
- 向右旋转 2 步: [6,7,1,2,3,4,5]
- 向右旋转 3 步: [5,6,7,1,2,3,4]
示例 2:
- 输入: [-1,-100,3,99] 和 k = 2
- 输出: [3,99,-1,-100]
- 解释:
- 向右旋转 1 步: [99,-1,-100,3]
- 向右旋转 2 步: [3,99,-1,-100]
说明:
- 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 要求使用空间复杂度为 O(1) 的原地算法。
解法:
- /**
- * @param {number[]} nums
- * @param {number} k
- * @return {void} Do not return anything, modify nums in-place instead.
- */
- var rotate = function(nums, k) {
- var k = k % nums.length;
- reverse(nums, 0, nums.length - 1);
- reverse(nums, k, nums.length - 1);
- reverse(nums, 0, k - 1);
- };
- var reverse = function(nums, i, j) {
- while(i < j) {
- swap(nums, i++, j--);
- }
- }
- var swap = function(nums, i, j) {
- var temp = nums[i];
- nums[i] = nums[j];
- nums[j] = temp;
- }
加一
给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
- 输入: [1,2,3]
- 输出: [1,2,4]
- 解释: 输入数组表示数字 123。
示例 2:
- 输入: [4,3,2,1]
- 输出: [4,3,2,2]
- 解释: 输入数组表示数字 4321。
解法:
- /**
- * @param {number[]} digits
- * @return {number[]}
- */
- var plusOne = function(digits) {
- if(digits.length == 0) return digits;
- var carry = 1;
- var res = [1];
- for(var i = digits.length - 1; i >= 0; i--) {
- if(carry == 0) return digits;
- var sum = carry + digits[i];
- digits[i] = sum % 10;
- carry = parseInt(sum / 10);
- }
- for(let i = digits.length - 1; i >= 0; i--) {
- res.push(0);
- }
- return carry == 0 ? digits : res;
- };
存在重复
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
- 输入: [1,2,3,1]
- 输出: true
示例 2:
- 输入: [1,2,3,4]
- 输出: false
示例 3:
- 输入: [1,1,1,3,3,4,3,2,4,2]
- 输出: true
解法 :
- /**
- * @param {number[]} nums
- * @return {boolean}
- */
- var containsDuplicate = function(nums) {
- let hashMap = new Map();
- for(let i = 0; i < nums.length; i++) {
- if( hashMap.has(nums[i]) ) {
- return true;
- }
- hashMap.set(nums[i], 1);
- }
- return false;
- };
移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
- 输入: [0,1,0,3,12]
- 输出: [1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
解法1:
- /**
- * @param {number[]} nums
- * @return {void} Do not return anything, modify nums in-place instead.
- */
- let moveZeroes = function(nums) {
- let n = nums.length;
- let slow = -1; // 指针索引
- let fast = 0; // 指针索引
- let x = 0;
- while(slow < fast && fast < n) {
- if (nums[fast] != x) {
- slow ++;
- swap(nums, slow, fast);
- }
- fast ++;
- }
- };
- let swap = function(nums, i, j) {
- let temp = nums[i];
- nums[i] = nums[j];
- nums[j] = temp;
- }
解法2:
- /**
- * @param {number[]} nums
- * @return {void} Do not return anything, modify nums in-place instead.
- */
- let moveZeroes = function(nums) {
- let n = nums.length;
- let one = 0;
- let x = 0;
- for(let i = 0; i < n; i ++) {
- if (nums[i] != x) {
- nums[one ++] = nums[i];
- }
- }
- for(let i = one; i < n; i ++) {
- nums[i] = x;
- }
- };
js 常见数组算法的更多相关文章
- JS常见排序算法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS常见的算法
原文链接:Jack Pu's Blog 虽说我们很多时候前端很少有机会接触到算法.实际上学习数据结构与算法对于工程师去理解和分析问题都是有帮助的.如果将来当我们面对较为复杂的问题,这些基础知识的积累可 ...
- JS中几种常见的数组算法(前端面试必看)
JS中几种常见的数组算法 1.将稀疏数组变成不稀疏数组 /** * 稀疏数组 变为 不稀疏数组 * @params array arr 稀疏数组 * @return array 不稀疏的数组 */ f ...
- 常见排序算法(JS版)
常见排序算法(JS版)包括: 内置排序,冒泡排序,选择排序,插入排序,希尔排序,快速排序(递归 & 堆栈),归并排序,堆排序,以及分析每种排序算法的执行时间. index.html <! ...
- Java基础语法(8)-数组中的常见排序算法
title: Java基础语法(8)-数组中的常见排序算法 blog: CSDN data: Java学习路线及视频 1.基本概念 排序: 是计算机程序设计中的一项重要操作,其功能是指一个数据元素集合 ...
- 常见排序算法原理及JS代码实现
目录 数组 sort() 方法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 堆排序 快速排序 创建时间:2020-08-07 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的 ...
- JavaScript版几种常见排序算法
今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...
- JS数据结构与算法-概述
JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
随机推荐
- 【scratch3.0教程】2.1 涂鸦花朵
第4课 涂鸦花朵 1.编程前的准备 在设计一个作品之前,必须先策划一个脚本,然后再根据脚本,收集或制作素材(图案,声音等)接着就可以启动Scratch,汇入角色,舞台,利用搭程序积木的方式编辑程 ...
- AS3.0 m3u8文件视频播放器
AS3.0 m3u8文件视频播放器(暂无源码): 点击欣赏! http://lxmc.aomaya.com/fengzi/m3u8/m3u8Player.swf
- Build step 'Send files or execute commands over SSH' changed build result to UNSTABLE
删除logs文件夹日志即可
- iTextSharp 不适用模板 代码拼接PDF
/// <summary> /// 打印移库单 /// </summary> /// <param name="guid"></param ...
- 2019年北航OO第4单元(UML)总结
1 架构设计 经过了接近一学期的程序设计训练,在这一单元的第一次作业中我就非常注重架构的设计,竭力避免像之前一样陷入"第一次作业凑合,第二次作业重构"的不健康的迭代模式.整体上来说 ...
- Linux 基础学习1
目录 Linux 基础学习 用户登录 终端 交互式接口 bash 修改ssh连接慢的步骤 命令提示符 显示提示符格式 命令 别名 命令格式 获取命令的帮助信息 man bash 快捷键 tab 键 引 ...
- php ajax生成excel并下载
目标:使用php,通过ajax请求的方式生成一个excel,然后下载. 思路:大致思路是发送一个ajax请求到后台,后台php处理后生成一个excel文件,然后把生成的文件放到一个临时目录,然后把文件 ...
- mysql的左连接问题
之前写过一个mysql语句,功能是将一个表ds的一个字段值同步更新到另一个表bk的字段,不过不是全部,只更新表bk中有的数据,如果表bk中有而表ds中没有,表B对应的这个字段值就为空 UPDATE b ...
- js求对象数组的交集/并集/差集/去重
1.求交集 var arr1 = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3}]; var arr1Id = [1,2,3] ...
- python之PEP8规范
比较需要注意的 缩进 每一级缩进使用4个空格. 续行应该与其包裹元素对齐,要么使用圆括号.方括号和花括号内的隐式行连接来垂直对齐,要么使用挂行缩进对齐3.当使用挂行缩进时,应该考虑到第一行不应该有参数 ...