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) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
随机推荐
- grafana部署安装
部署grafana 在prometheus& grafana server节点部署grafana服务. 1. 下载&安装 # 下载 [root@prometheus ~]# cd /u ...
- ABP 基于DDD的.NET开发框架 学习(六)创建新动态Api
我们想要这个服务暴露成一个Web API控制器,以方便客户端调用.ASP.NET Boilerplate能够自动且动态地为这个应用服务创建Web API 控制器,只需要一行配置代码即可完成. Dyna ...
- 安装Ubuntu18.04系统
一.安装Ubuntu系统 进入系统安装的第一个界面,开始系统的安装操作.每一步的操作,左下角都会提示操作方式!! 1.选择系统语言-English 2.键盘设置-English 3.选择操作Insta ...
- 线程池ThreadPool实战
线程池ThreadPool 线程池概念 常用线程池和方法 1.测试线程类 2.newFixedThreadPool固定线程池 3.newSingleThreadExecutor单线程池 4.newCa ...
- python多线程爆破压缩包密码
import zipfile from threading import Thread #多线程库 import optparse #选定字典或者文件 def extractFile(zfile,pa ...
- AI人脸识别SDK接入 — 参数优化篇(虹软)
引言 使用了虹软公司免费的人脸识别算法,感觉还是很不错的,当然,如果是初次接触的话会对一些接口的参数有些疑问的.这里分享一下我对一些参数的验证结果(这里以windows版本为例,linux.andro ...
- 设置redis开机自动启动
注意:win7执行命令前面可不需要加路径,win10必须要加路径 命令: redis-server --service-install redis.windows.conf 执行完成之后,打开服务管理 ...
- Python学习日记(十二) 匿名函数
匿名函数: 未解决一些简单的需求而设计的函数 语法: func = lambda x : x**2 func:函数名 lambda:类似def的关键字 x:参数 x**2:返回值表达式 适用内置函数: ...
- websocket趣说_转
websocket协议:https://tools.ietf.org/html/rfc6455 作者:Ovear链接:https://www.zhihu.com/question/20215561/a ...
- Python_Day2_共享你的代码
一.编写简单的函数,保存一下. # coding=utf-8 """ 这是“nester.py”模块,提供了一个名为print_lol的函数,这个函数的作用是打印列表,其 ...