1. 给定两个数组,编写一个函数来计算它们的交集。示例 1:输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
const intersect = function(nums1, nums2) {
const result = []
for(let i = 0; i< nums1.length; i++) {
const existIndex = nums2.findIndex(item => item===nums1[i])
if (existIndex >= 0) {
result.push(nums1[i])
nums2.splice(existIndex, 1)
}
}
return result
};
3. 解析url的query
function qsParse(str) {
function deep_set(obj, key, value) {
const path = key.split(/[\[\]]/).filter(x => x)
// path = [name, name]
let i = 0
for (; i< path.length -1; i++) {
if (obj[path[i]] === undefined) {
// 没有属性
if (path[i+1].match(/\d+/)) {
obj[path[i]] = []
} else {
obj[path[i]] = {}
}
}
obj = obj[path[i]]
}
obj[path[i]] = decodeURIComponent(value)
}
return str.split('&').reduce((acc, item) => {
const [key, value] = item.split('=')
if (!value) {
return acc
}
deep_set(acc, key, value)
return acc
}, {})
}
console.log(qsParse('name=xiaoxiao&age=18'))
console.log(qsParse('name&age'))
console.log(qsParse('name[name]=xiao xiao&age=18'))
console.log(qsParse('name[12]=xiaoxiao&age=18'))
console.log(qsParse('name=xiaoxiao'))
4. sumN([1,3, 8, 5, 2], 2, 11) 得出[3, 8]
// 递归
function sumN(arr, m, n) {
let r = null
const decision = []
function inner(i = 0, m, n) {
console.log(decision, i, m, n)
if (r) return
if (n === 0) {
r = decision.slice()
return
}
if (n < 0 || m === 0 || i === arr.length) {
return;
}
decision.push(arr[i])
inner(i+1, m-1, n-arr[i])
decision.pop(arr[i])
inner(i+1, m, n)
}
inner(0, m, n)
return r
}
sumN([1, 2, 3, 4, 5], 3, 10)
// 方便理解:答应出decision, i, m, n
[] 0 3 10
[ 1 ] 1 2 9
[ 1, 2 ] 2 1 7
[ 1, 2, 3 ] 3 0 4
[ 1, 2 ] 3 1 7
[ 1, 2, 4 ] 4 0 3
[ 1, 2 ] 4 1 7
[ 1, 2, 5 ] 5 0 2
[ 1, 2 ] 5 1 7
[ 1 ] 2 2 9
[ 1, 3 ] 3 1 6
[ 1, 3, 4 ] 4 0 2
[ 1, 3 ] 4 1 6
[ 1, 3, 5 ] 5 0 1
[ 1, 3 ] 5 1 6
[ 1 ] 3 2 9
[ 1, 4 ] 4 1 5
[ 1, 4, 5 ] 5 0 0
[ 1, 4 ] 5 1 5
[ 1 ] 4 2 9
[] 1 3 10
5. 排序
5.1 冒泡排序
- 外层循环n-1次
- 内层循环n-1-i次
function bubbleSort(arr) {
let count = arr.length
while(count) {
for(let i = 0; i < count - 1; i++) {
if (arr[i] > arr[i+1]) {
[arr[i], arr[i+1]] = [arr[i+1], arr[i]]
}
}
count--
}
return arr
}
console.log(bubbleSort([1, 5, 4, 6, 0, 3])) // [0, 1, 3, 4, 5, 6]
5.2 插入排序
- 类似抓牌,先取一张,取的每一张和之前的牌做对比,大的放右,小的放左
function insertSort(arr) {
const result = []
result.push(arr[0])
for(let i = 1; i < arr.length -1; i++) {
for(let j = result.length -1; j >= 0; j--) {
if (arr[i] > result[j]) {
result.splice(j+1, 0, arr[i])
break
}
if (j === 0) {
result.unshift(arr[i])
}
}
}
return result
}
console.log(insertSort([1, 5, 4, 6, 0, 3])) // [0, 1, 3, 4, 5, 6]
5.3 快速排序
- 找中间的,大的在右,小的在左,递归
function quickSort(arr) {
if (arr.length <= 1) {
return arr
}
const middle = Math.floor(arr.length/2)
const [ middleItem ] = arr.splice(middle, 1)
const leftArr = [], rightArr = [];
for (let i = 0; i < arr.length; i++) {
arr[i] > middleItem ? rightArr.push(arr[i]) : leftArr.push(arr[i])
}
return quickSort(leftArr).concat(middleItem, quickSort(rightArr))
}
console.log(quickSort([1, 5, 4, 6, 0, 3])) // [0, 1, 3, 4, 5, 6]
6. 反转二叉树
function reverseBTree(node) {
if (!node) {
return
}
const temp = node.left
node.left = node.right
node.right = temp
reverseBTree(node.left)
reverseBTree(node.right)
}
7 求一个二叉树从左侧看的轮廓,如图,返回【1, 5, 4, 8】? 如果求每行的最大值怎么做
function outlineTree(node, d = 0, outline = []) {
// 深度优先,先遍历左
if (!node) {
return outline
}
if (!outline[d]) {
outline[d] = node.value
}
outlineTree(node.left, d + 1, outline)
outlineTree(node.right, d + 1, outline)
return outline;
}
// 求最大
function outMaxTree(node, d = 0, outline = []) {
if (!node) return outline;
outline[d] = Math.max(outline[d] || -1, node.value)
outMaxTree(node.left, d + 1, outline)
outMaxTree(node.right, d + 1, outline)
return outline
}
在此复习一下二叉树的相关知识
- 二叉事有且只有一个根结点
- 每个节点做多有两个子节点
- 左边的值大于右边的值
构造一颗二叉树
function Node(value) {
this.value = value
this.left = null
this.right = null
}
let root = null
function insert(value) {
const newNode = new Node(value)
if (!root) {
root = newNode
} else {
insertNode(root, newNode)
}
function insertNode(node, newNode) {
if (node.value > newNode.value) {
if (!node.left) {
node.left = newNode
} else {
insertNode(node.left, newNode)
}
} else {
if (!node.right) {
node.right = newNode
} else {
insertNode(node.right, newNode)
}
}
}
}$

insert(8)
insert(4)
insert(9)
insert(1)
insert(0)
insert(6)
打印二叉树:
二叉树的遍历
function travel(node, callback) {
if (node === null) return
callback(node.value)
travel(node.left, callback)
travel(node.right, callback)
}
travel(root, value => {
console.log(value)
})
// 8 4 1 0 6 9 先序遍历
- 先序遍历(根左右)
callback(node.value)
travel(node.left, callback)
travel(node.right, callback) // 8 4 1 0 6 9
- 中序遍历(左根右)
...
travel(node.left, callback)
callback(node.value)
travel(node.right, callback) // 0 1 4 6 8 9
- 后序遍历(左右拫)
...
travel(node.left, callback)
travel(node.right, callback)
callback(node.value) // 0 1 6 4 9 8
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
var findKthLargest = function(nums, k) {
function bubbleSort(nums) {
let count = nums.length
while(count) {
for(let i = 0; i < count -1; i++) {
if (nums[i] < nums[i+1]) {
[nums[i], nums[i+1]] = [nums[i+1], nums[i]]
}
}
count--
}
return nums
}
const sortArr = bubbleSort(nums)
return sortArr[k -1]
};
数组的去重和排序
- new Set()
// 'new Set()'
set [...new Set(arr)]
- indexOf,或者includes,性能不好
// 'indexOf或者includes'
+ 在原有基础上操作
方法一:
let arr = [12, 14,13, 16, 28, 99, 13, 12]
// 拿当前的和后边的找
function uniqArr(arr) {
for(let i = 0; i < arr.length; i++) {
let otherArr = arr.slice(i + 1)
if (otherArr.indexOf(arr[i]) > -1) { // 或者includes
arr.splice(i, 1)
i-- // 存在数组塌陷的问题
}
}
return arr
}
console.log(uniqArr(arr))
方法二:
+ '将存在的项变为null,再使用filter'
let arr1 = [12, 14,13, 16, 28, 99, 13, 12, ]
function uniqArr(arr) {
for(let i = 0; i < arr.length; i++) {
let otherArr = arr.slice(i + 1)
if (otherArr.indexOf(arr[i]) > -1) { // 或者includes
arr[i] = null
}
}
return arr.filter(x => x)
}
console.log(uniqArr(arr1))
方法三:
// '开辟一个新的堆内存存放数组'
function uniqArr(arr) {
let newArr = []
for(let i = 0; i < arr.length; i++) {
if(arr.slice(i+1).indexOf(arr[i]) === -1) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(uniqArr(arr))
方法四:
// '如果存在用最后一项替代当前项,并删除最后一项,i--'
function uniqArr(arr) {
for(let i = 0; i < arr.length; i++) {
let otherArr = arr.slice(i + 1)
if (otherArr.indexOf(arr[i]) > -1) { // 或者includes
arr[i] = arr.pop()
i--
}
}
return arr
}
console.log(uniqArr(arr))
- 对象键值对
function uniqArr(arr) {
let obj = {}
for(let i = 0; i < arr.length; i++) {
let item = arr[i]
if (typeof obj[item] !== 'undefined') {
arr[i] = arr[arr.length -1]
arr.length--
i--
continue
}
obj[item] = item
}
return arr
}
数组扁平化
- flatten扁平化
- 数组转成字符串
// 方法1
let arr = [1, [2, 3, [4, 5, [6, 7]]]]
function flat(arr) {
return arr.toString().split(',').map(item => parseInt(item))
}
console.log(flat(arr))
// 方法二
let arr = [1, [2, 3, [4, 5, [6, 7]]]]
function flat(arr) {
return JSON.stringify(arr).replace(/[\[\]]/g, '').split(',').map(x => parseInt(x))
}
console.log(flat(arr))
- 循环验证每一项是不是数组
let arr = [1, [2, 3, [4, 5, [6, 7]]]]
// 方法一:
function flat(arr) {
while(arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flat(arr))
// 方法二:
- 递归
let arr = [1, [2, 3, [4, 5, [6, 7]]]]
function flat(arr) {
let newArr = []
const fn = (arr) => {
for(let i = 0; i< arr.length; i++) {
if (Array.isArray(arr[i])) {
fn(arr[i])
} else {
newArr.push(arr[i])
}
}
}
fn(arr)
return newArr
}
console.log(flat(arr))
斐波那契数列
- 前两项是1,之后每一项是之前两项的和
function fibe(index) {
function fn(index, first = 1, second = 1) {
if (index <= 1) {
return 1
}
return fibe(index -1) + fibe(index-2)
}
return fn(index)
}
console.log(fibe(4)) //5
输出和为n的所有正数序列
- 连续整数的和: n + (m+n-1)* m /2
function fn(count) {
const createArr = (i, len) => {
let arr = new Array(len).fill(i)
arr = arr.map((x, index) => {
return x+index
})
return arr
}
let middle = Math.ceil(count/2) // 取中间的数字
let arr = []
for(let i = 1; i <= middle; i++) {
for(let j = 2;;j++) {
const total = (i+(i+j-1))*(j/2)
if (total > count) {
break
} else if(total === count){
arr.push(createArr(i, j))
break
}
}
}
return arr
}
console.log(fn(15))