js 算法
提高性能的点
- 对象尽量使用 es6 解构方式,尽量少的去访问引用类型
- 不要过多频繁的使用 push,会影响性能
数组去重
- 两个循环判断
判断问题:拿第一个和每一个去做比较,所以需要用到两个循环;
(1)写两个循环,第一个循环数组第一个数据,第二个循环让每一个和第一个做比较。
(2)第二循环 j=i+1,再判断第二个循环的下标是否和第一个循环的下标的字符相同,如果是相同的,则删除一个
(3)删除之后数组变短,让 j 减一,重新做比较。
js
for (var i = 0; i < ary.length; i++) {
for (var k = i + 1; k < ary.length; k++) {
if (ary[i] === ary[k]) {
if (i == k) {
//如果k等于0,则需要这一步
continue
}
ary.splice(k, 1)
k--
//前面删除一个之后数组的长度会进1,此时的k会直接跳到循环去加1,让k减1;
}
}
}for (var i = 0; i < ary.length; i++) {
for (var k = i + 1; k < ary.length; k++) {
if (ary[i] === ary[k]) {
if (i == k) {
//如果k等于0,则需要这一步
continue
}
ary.splice(k, 1)
k--
//前面删除一个之后数组的长度会进1,此时的k会直接跳到循环去加1,让k减1;
}
}
}- 使用 set 去重
js
Array.from(new Set([1,2,2,3])Array.from(new Set([1,2,2,3])- 使用 reduce 去重
js
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
if (!pre.includes(cur)) {
return pre.concat(cur)
} else {
return pre
}
}, [])let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
if (!pre.includes(cur)) {
return pre.concat(cur)
} else {
return pre
}
}, [])- 使用 filter 去重;
js
function unique(array) {
var str = ''
return array.filter((item) => {
//利用filter过滤返回true的情况;
// 判断字符串中有没有,如果有,则return;
if (str.includes(typeof item + item)) return
return (str += typeof item + item) // 如果没有,则存入,返回true;
})
}function unique(array) {
var str = ''
return array.filter((item) => {
//利用filter过滤返回true的情况;
// 判断字符串中有没有,如果有,则return;
if (str.includes(typeof item + item)) return
return (str += typeof item + item) // 如果没有,则存入,返回true;
})
}数组乱序
- 原地洗牌,不需要声明额外的数组从而更加节约内存占用率,
原理:依次遍历数组的元素,将当前元素和之后的所有元素中随机选取一个,进行交换
js
function shuffle(arr){
for(let i=0;i<arr.length;i++){
// 由于下标从0开始,length从1开始因此使用floor向下取整;
let index= i + Math.floor(Math.random()*arr.length);
[arr[i],arr[index]] = [arr[index],arr[i]]; // 这里使用了es6的交换位置方法
}
return arr
} // 传入一个数组则乱序function shuffle(arr){
for(let i=0;i<arr.length;i++){
// 由于下标从0开始,length从1开始因此使用floor向下取整;
let index= i + Math.floor(Math.random()*arr.length);
[arr[i],arr[index]] = [arr[index],arr[i]]; // 这里使用了es6的交换位置方法
}
return arr
} // 传入一个数组则乱序- 非原地洗牌
js
function sort2(arr) {
let arr2 = []
while (arr.length) {
// arr的长度会越来越少; 实现随机生成的乱序;
let index = Math.floor(Math.random() * arr.length)
arr2.push(arr.splice(index, 1)[0])
}
return arr2
}function sort2(arr) {
let arr2 = []
while (arr.length) {
// arr的长度会越来越少; 实现随机生成的乱序;
let index = Math.floor(Math.random() * arr.length)
arr2.push(arr.splice(index, 1)[0])
}
return arr2
}- 使用 sort 进行乱序
js
let sort2 = (arr) => arr.sort(() => Math.random() - 0.5)let sort2 = (arr) => arr.sort(() => Math.random() - 0.5)数组排序
- 选择数组排序
判断问题:拿第一个和每一个去做比较,如果大于第二个,则让第一个到第二个位置去;
(1)写两个循环,第二个循环 j=i+1;,不比较本身。
(2)判断数组的第一个字符 i 是否大于数组的第二个 j 字符,如果大于第一个字符,则调换位置。
- 冒泡数组排序
js
for (var i = 0; i < ary.length; i++) {
for (var k = 0; k < ary.length; k++) {
if (ary[k] > ary[k + 1]) {
//2k > 1n 1n 2k
var n = ary[k]
ary[k] = ary[k + 1]
ary[k + 1] = n
} //自身和紧挨着的后一个比较;
}
}for (var i = 0; i < ary.length; i++) {
for (var k = 0; k < ary.length; k++) {
if (ary[k] > ary[k + 1]) {
//2k > 1n 1n 2k
var n = ary[k]
ary[k] = ary[k + 1]
ary[k + 1] = n
} //自身和紧挨着的后一个比较;
}
}- sort()排序
js
arr.sort();
从大到小==> arr.sort((a,b)=>b-a)arr.sort();
从大到小==> arr.sort((a,b)=>b-a)对象拷贝方法
浅拷贝:...扩展运算符浅拷贝;
js
var obj = { a: 'haha', b: { c: 'haha' } }
var obj2 = { ...obj }
obj.b.c = 'lalala'
console.log(obj2.b.c) // 'lalala'var obj = { a: 'haha', b: { c: 'haha' } }
var obj2 = { ...obj }
obj.b.c = 'lalala'
console.log(obj2.b.c) // 'lalala'深拷贝:
- JSON 方法
js
let obj = { name: 'zs', age: 18 }
let obj2 = JSON.parse(JSON.stringify(obj))
obj2.name = 'ww'let obj = { name: 'zs', age: 18 }
let obj2 = JSON.parse(JSON.stringify(obj))
obj2.name = 'ww'- jquery 深拷贝
js
var obj2 = $.extend(true, {}, obj3)var obj2 = $.extend(true, {}, obj3)- 浅拷贝+递归
js
// 第二个参数可传可不传;
function deepClone(origin,target={}){
for(let prop in origin){
// 不拷贝原型上的内容;
if(origin.hasOwnProperty(prop){
// 判断该值还是不是一个对象;
if(typeof origin[prop] === 'object'){
// 判断一下类型,并进行拷贝;
target[prop] = Array.isArray(origin[prop]) ? [] : {}
deepClone(origin[prop],target[prop])
} else {
target[prop] = origin[prop]
}
}
}
return target
}// 第二个参数可传可不传;
function deepClone(origin,target={}){
for(let prop in origin){
// 不拷贝原型上的内容;
if(origin.hasOwnProperty(prop){
// 判断该值还是不是一个对象;
if(typeof origin[prop] === 'object'){
// 判断一下类型,并进行拷贝;
target[prop] = Array.isArray(origin[prop]) ? [] : {}
deepClone(origin[prop],target[prop])
} else {
target[prop] = origin[prop]
}
}
}
return target
}对象合并
- jquery
js
var obj2 = $.extend({}, obj1, obj3, obj4)var obj2 = $.extend({}, obj1, obj3, obj4)- vue 中
js
vm.userPro = Object.assign({}, obj1, obj2)vm.userPro = Object.assign({}, obj1, obj2)扁平化数组
reduce
js
let arr = [1, 2, [3, 4, [5, 6]]]
function fn(arr) {
return arr.reduce((p, c) => {
return p.concat(Array.isArray(c) ? fn(c) : c)
}, [])
}
fn(arr) // [1,2,3,4,5,6]let arr = [1, 2, [3, 4, [5, 6]]]
function fn(arr) {
return arr.reduce((p, c) => {
return p.concat(Array.isArray(c) ? fn(c) : c)
}, [])
}
fn(arr) // [1,2,3,4,5,6]toString和split方法,仅对数字有效
js
let arr = [1, 2, [3, 4, [5, 6]]]
let arr2 = JSON.parse(`[${arr.toString()}]`)let arr = [1, 2, [3, 4, [5, 6]]]
let arr2 = JSON.parse(`[${arr.toString()}]`)- 使用递归遍历
js
let arr = [1,2,[3,4,[5,6]]]
function fn(arr){
let res = []
arr.map(item=>{
if(Array.isArray(item){
res = res.concat(fn(item)) // 将调用的结果合并
}
res.push(item)
})
return res
}let arr = [1,2,[3,4,[5,6]]]
function fn(arr){
let res = []
arr.map(item=>{
if(Array.isArray(item){
res = res.concat(fn(item)) // 将调用的结果合并
}
res.push(item)
})
return res
}flat() 括号里面传入数字,表示扁平化几个,当传入 Infinity 时,会扁平所有的数组;
js
var arr = [1[,2,3,[4,5,6]]]
arr.flat(Infinity)var arr = [1[,2,3,[4,5,6]]]
arr.flat(Infinity)- 使用...扩展运算符,最实用的一个方法
js
let arr = [1, 2, [{ name: 'h' }, [{ age: 18 }]]]
while (arr.some(Array.isArray)) {
arr = [].concat(...arr)
}
console.log(arr)let arr = [1, 2, [{ name: 'h' }, [{ age: 18 }]]]
while (arr.some(Array.isArray)) {
arr = [].concat(...arr)
}
console.log(arr)力扣题
查找下列数据 id 为 xx 的数据
var arr = [{
id: 3,
name: "gao"
}, {
id: 4,
name: 4,
child: [
{
id: 3,
name: "gao3"
}
]
}]
function getById(data,id){
let arr = []
for(var i = 0;i<data.length;i++){
if(data[i].id==id){
arr.push(data[i])
}
if(data[i].child){
arr.push(...getById(data[i].child,id))
}
}
return arr
}
console.log(getById(arr,3));var arr = [{
id: 3,
name: "gao"
}, {
id: 4,
name: 4,
child: [
{
id: 3,
name: "gao3"
}
]
}]
function getById(data,id){
let arr = []
for(var i = 0;i<data.length;i++){
if(data[i].id==id){
arr.push(data[i])
}
if(data[i].child){
arr.push(...getById(data[i].child,id))
}
}
return arr
}
console.log(getById(arr,3));两数之和
js
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]jsx
map解法
var twoSum = function (nums, target) {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
if (map.has(target - nums[i])) {
return [map.get(target - nums[i]), i]
} else {
map.set(nums[i], i)
}
}
}
双for循环
var twoSum = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length + 1; j++) {
if (target - nums[i] === nums[j]) {
return [i, j]
}
}
}
}map解法
var twoSum = function (nums, target) {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
if (map.has(target - nums[i])) {
return [map.get(target - nums[i]), i]
} else {
map.set(nums[i], i)
}
}
}
双for循环
var twoSum = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length + 1; j++) {
if (target - nums[i] === nums[j]) {
return [i, j]
}
}
}
}寻找两个正序数组的中位数
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2jsx
var findMedianSortedArrays = function (nums1, nums2) {
let arr = nums1.concat(nums2).sort((a, b) => a - b)
return arr.length % 2
? arr[Math.floor(arr.length / 2)]
: (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2
}var findMedianSortedArrays = function (nums1, nums2) {
let arr = nums1.concat(nums2).sort((a, b) => a - b)
return arr.length % 2
? arr[Math.floor(arr.length / 2)]
: (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2
}回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。jsx
var isPalindrome = function (x) {
if (x < 0 || (x > 0 && x % 10 === 0)) return false
let x2 = x,
res = 0
while (x2) {
res = res * 10 + (x2 % 10)
x2 = Math.floor(x2 / 10)
}
return res === x
}var isPalindrome = function (x) {
if (x < 0 || (x > 0 && x % 10 === 0)) return false
let x2 = x,
res = 0
while (x2) {
res = res * 10 + (x2 % 10)
x2 = Math.floor(x2 / 10)
}
return res === x
}罗马数字转整数
jsx
var romanToInt = function (s) {
const map = {
I: 1,
IV: 4,
V: 5,
IX: 9,
X: 10,
XL: 40,
L: 50,
XC: 90,
C: 100,
CD: 400,
D: 500,
CM: 900,
M: 1000,
}
let num = 0
for (let i = 0; i < s.length; ) {
if (map[s.substring(i, i + 2)]) {
num += map[s.substring(i, i + 2)]
i += 2
} else {
num += map[s[i]]
i++
}
}
return num
}var romanToInt = function (s) {
const map = {
I: 1,
IV: 4,
V: 5,
IX: 9,
X: 10,
XL: 40,
L: 50,
XC: 90,
C: 100,
CD: 400,
D: 500,
CM: 900,
M: 1000,
}
let num = 0
for (let i = 0; i < s.length; ) {
if (map[s.substring(i, i + 2)]) {
num += map[s.substring(i, i + 2)]
i += 2
} else {
num += map[s[i]]
i++
}
}
return num
}寻找两个正序数组的中位数
jsx
var findMedianSortedArrays = function (nums1, nums2) {
let arr = nums1.concat(nums2).sort((a, b) => a - b)
const len = arr.length
return len % 2 ? arr[Math.floor(len / 2)] : (arr[len / 2 - 1] + arr[len / 2]) / 2
}var findMedianSortedArrays = function (nums1, nums2) {
let arr = nums1.concat(nums2).sort((a, b) => a - b)
const len = arr.length
return len % 2 ? arr[Math.floor(len / 2)] : (arr[len / 2 - 1] + arr[len / 2]) / 2
}判断一个字符串"{a(b[c]d)e}f"是否括号匹配
jsx
function matchBracket(str) {
let len = str.length
if (len === 0) return true
let stack = []
let left = '{[('
let right = '}])'
for (let i = 0; i < len; i++) {
let s = str[i]
if (left.includes(s)) {
stack.push(s)
} else if (right.includes(s)) {
let a = stack[stack.length - 1]
if (isMatch(a, s)) {
stack.pop()
} else {
return false
}
}
}
return stack.length === 0
}
function isMatch(left, right) {
if (left === '{' && right === '}') return true
if (left === '[' && right === ']') return true
if (left === '(' && right === ')') return true
return false
}
console.log(matchBracket('{a(b[c]d)e}}'))function matchBracket(str) {
let len = str.length
if (len === 0) return true
let stack = []
let left = '{[('
let right = '}])'
for (let i = 0; i < len; i++) {
let s = str[i]
if (left.includes(s)) {
stack.push(s)
} else if (right.includes(s)) {
let a = stack[stack.length - 1]
if (isMatch(a, s)) {
stack.pop()
} else {
return false
}
}
}
return stack.length === 0
}
function isMatch(left, right) {
if (left === '{' && right === '}') return true
if (left === '[' && right === ']') return true
if (left === '(' && right === ')') return true
return false
}
console.log(matchBracket('{a(b[c]d)e}}'))实现数字千分位格式化
jsx
function formatl(n) {
n = Math.floor(n)
let s = n.toString()
let arr = s.split('').reverse()
return arr.reduce((perv, val, index) => {
if (index % 3 === 0) {
s
if (perv) {
return val + ',' + perv
} else {
return val
}
} else {
return val + perv
}
})
}
console.log(formatl(1234567895))
sfunction formatl(n) {
n = Math.floor(n)
let s = n.toString()
let arr = s.split('').reverse()
return arr.reduce((perv, val, index) => {
if (index % 3 === 0) {
s
if (perv) {
return val + ',' + perv
} else {
return val
}
} else {
return val + perv
}
})
}
console.log(formatl(1234567895))
s
Cao Note