前言
最近学习中发现自己算法部分相对薄弱,所以持续一段时间的练习来提高自己的算法能力,顺带熟悉js及es6的基础对象方法。
题目部分
- 防抖和节流的实现?
防抖:
// 防抖
function debounce (func, wait) {
var timeOut
return function () {
clearTimeout(timeOut)
timeOut = setTimeout(func, wait)
}
}
function mydefunc () {
console.log('oo')
}
// window.addEventListener('scroll', debounce(mydefunc, 300))
节流:
// 节流
function throttle (func, wait, maxTime) {
var timeOut
var startTime = new Date()
return function () {
var curTime = new Date()
that = this
args = arguments
clearTimeout(timeOut)
if (curTime - startTime >= maxTime) {
func.apply(that, args)
startTime = curTime
} else {
timeOut = setTimeout(func, wait)
}
}
}
// window.addEventListener('scroll', throttle(mydefunc, 500, 1000))
- 对象的深拷贝
function deepCopy (obj) {
var newObj = {}
for (let key in obj) {
if (obj[key] instanceof Array) {
newObj[key] = [...obj[key]]
} else if (obj[key] instanceof Object) {
newObj[key] = deepCopy(obj[key])
} else {
newObj[key] = obj[key]
}
}
return newObj
}
var obj = {
a: 'haha',
b: 'hehe',
c: 'heihei',
d: {
x: 'en',
y: 'yes'
},
e: [3, 5]
}
var newObj = deepCopy(obj)
newObj.d.x = 'pipi'
newObj.e.pop()
// 以下两个输出不同
console.log(obj)
console.log(newObj)
- 实现数组的堆排序
// 将整个数组看成一个完全二叉树 即堆
function swap (arr, i, j) {
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
// 排序————将每个拥有度的节点与其子节点比较,若关键值比子节点小则交换反之亦然,总之使父节点拥有最大的关键值
// 从第一个指定节点开始逐层往下做交换直至指定节点以下变成 大顶堆
function shiftDown(arr, i, length) {
let temp = arr[i]
for (let j = 2*i+1; j < length; j = 2*j+1) {
temp = arr[i]
if ( j+1 < length && arr[j] < arr[j+1]) {
j++
}
if (temp < arr[j]) {
swap(arr, i, j)
i = j
} else {
break
}
}
}
// 第一个for将二叉树的第一个非叶子节点作为根节点使用shiftDown排序
// 第二个for则将大顶堆的根节点(值最大)与最后一个节点交换(相当于放在数组的最末尾),然后数组长度-1继续再从根节点排序
function duiSort(arr) {
for (let i = Math.floor(arr.length/2 - 1); i >= 0; i--) {
shiftDown(arr, i, arr.length)
}
for (let i = Math.floor(arr.length - 1); i > 0; i--) {
swap(arr, 0, i)
shiftDown(arr, 0, i)
}
}
let arr = [5, 6, 2, 1, 8, 3, 7, 9, 4, 3, 6]
duiSort(arr)
console.log(arr)
- 如何实现顺序数组的随机排序?
// 实现思路:通过每一轮循环将数组中随机的位置里的值和循环位置上的值交换来达到数组的随机排序
var arr = [1,2,3,4,5,6,7,8,9,10];
function randomArr(arr){
for(var i = 0;i < arr.length;i++ ){
var rand = parseInt(Math.random()*arr.length);
var temp = arr[rand];
arr[rand] = arr[i];
arr[i] = temp;
}
return arr;
}
console.log(randomArr(arr));
- 输入一个字符串年份(如:2016-01-13),输出是当年的第多少天(输出:13)
var date = '2016-01-04'
date = date.split('-')
var arrMonth = [31, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
var totalDay = 0
if (date[0] % 4 === 0) {
arrMonth.splice(1, 0, 29)
} else {
arrMonth.splice(1, 0, 28)
}
if (date[1] === '01') {
totalDay += Number(date[2])
} else {
for (let i = 0; i < Number(date[1]) - 1; i++) {
totalDay += arrMonth[i]
}
totalDay += Number(date[2])
}
console.log(totalDay);
- 输出99乘法表?
for(var i=1;i<=9;i++){
document.write('<div class="myDiv">')
for(var j=1;j<=i;j++){
document.write('<span class="mySpan">'+ i + '*' + j + '=' + i*j + '</span>')
}
document.write('</div>')
}
// 两层循环实现,可以通过类名改变样式
- 实现数组按照中间高两边低进行排序的方法?
var arr = [3,9,4,21,1,12,6,4,2,9,1,13,11,17,29,31,33]
function newArr (arr) {
// 先判断数组长度为奇或偶数
if ((arr.length % 2) === 0) {
// 为偶数时
// 分为两部分,左边从小到大排列,右边从大到小排列
let arrLeft = arr.slice(0,arr.length / 2)
let arrRight = arr.slice((arr.length / 2) + 1)
arrLeft.sort((a, b) => a - b)
arrRight.sort((a, b) => b - a)
return arrLeft.concat(arrRight)
} else {
// 否则为奇数时
// 先找出最大的数移除,再按偶数中的方法处理后拼接
var maxNum = Math.max(...arr)
arr.splice(arr.indexOf(maxNum),1)
let arrLeft = arr.slice(0,arr.length / 2)
let arrRight = arr.slice((arr.length / 2) + 1)
arrLeft.sort((a, b) => a - b)
arrRight.sort((a, b) => b - a)
return arrLeft.concat(maxNum,arrRight)
}
}
console.log(newArr(arr))
- 去掉数组中的重复项,并按升序排序?
// 方法一
var arr = [3,9,4,21,1,12,6,4,2,9,1,13,11,17,29,3,6]
function newArr (arr) {
var newArr = []
arr.forEach(element => {
// 便利每个元素,当arr中第一个出现此元素的下标等于最后一次出现的下标时则认为该元素没重复
if (newArr.indexOf(element) === -1) {
// 将没重复的数压入新数组
newArr.push(element)
}
})
//从小到大排序
newArr.sort((a, b) => a - b)
return newArr
}
console.log(newArr(arr))
// 方法二 (运用es6的set查重)
var arr = [3,9,4,21,1,12,6,4,2,9,1,13,11,17,29,3,6]
function newArr (arr) {
var newArr = [...new Set(arr)]
newArr.sort((a,b) => a-b)
return newArr
}
console.log(newArr(arr))
- 实现斐波那契数列
斐波那契数列: 前两个数为1,2,后面的数依次为前两个数相加。(如1,2,3,5,8,13,21,······这样的数列叫做斐波那契数列)
// 递归实现(传入数字太大可能造成浏览器假死)
function Fibonacci(n) {
if (n === 1 || n === 2) {
return 1
} else {
return Fibonacci(n-1) + Fibonacci(n-2)
}
}
console.log(Fibonacci(6))
- 给定一个对象obj,输出obj第一项的值
// 给定对象
var obj = {
name : "oyjh",
age : 22,
job : "Front-end Engineer",
hobby: "sing,dance,guitar,photography"
}
console.log((() => {
// 采用循环处理输出第一项的值
var value = []
for (let key in obj) {
value.push(obj[key])
}
return value[0]
})())
- 给定一个字符串,每隔n个字符就用逗号隔开?
// 方法一
function splitStr(str, n) {
let newStr = new String(str)
let arr = []
//先判定循环几次(如果字符串长度除以n为小数时需要向上舍入)
for (let i = 0;i < Math.ceil(newStr.length/n); i++) {
// 循环的第几次*每次截取的长度n就是 当前从哪里开始截取(也可以用substring如方法二)
arr.push(newStr.substr(i*n, n))
}
console.log(arr.join(','))
}
splitStr('12342232阿萨德212d大神dasdw', 3)
// 方法二
function splitStr(str, n) {
let newStr = '';
for (let i = 0; i < str.length; i++) {
if (i % n === 0) {
newStr += str.substring(i, i + n) + ','
}
}
console.log(newStr.substring(0, newStr.length - 1)) //去掉最后一个逗号
}
splitStr('12342232阿萨德212d大神dasdw', 3)
- 翻转一个给定字符串
function reverseStr(str) {
let arr = new String(str).split('')
// 不能用toString,字符串会有逗号分割
let newStr = arr.reverse().join('')
console.log(newStr)
}
reverseStr('12342232阿萨德212d大神dasdw')
- 判断给定字符串是不是回文?
回文:如果一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文)。
function isPalindrome(str) {
// 先去掉多余的符号,空格等再转换为小写字符
let oldStr = new String(str).replace(/[^\w]/g, '').toLowerCase()
// console.log(newStr) 输出abc1d42efg000h000gfe24d1cb
// 反转字符串
let newStr = oldStr.split('').reverse().join('')
// 判断是否是回文
if (oldStr === newStr) {
console.log('是回文字符串')
} else {
console.log('不是')
}
}
isPalindrome("aBc,./1d42--==EFG0 00 h0-';'00gfE';./. 24d 1cBA")
- 找到给定英文短句中最长的单词输出?
function longerWord(str) {
let newStr = new String(str)
// 给定的英文句子转化为数组存储
var arr = newStr.split(' ')
var maxWord = []
// 数组按每个元素长度从大到小排序
arr.sort((a, b) => b.length - a.length)
//先将第一个最长的单词压入maxWord
maxWord.push(arr[0])
// 循环判断是否有最长长度一样的单词
for (let i = 1; i < arr.length; i++) {
if(arr[0].length === arr[i].length) {
maxWord.push(arr[i])
}
}
// 转化为字符串输出
console.log(maxWord.join(' '))
}
longerWord("my name is oyjh")
- 使句子中每个单词首字母大写并输出?
// 方法一:正则
function titleCase(str) {
// 利用正则表达式来查询英文短句中的单词,并修改首字母为大写替换
let newStr = new String(str).replace(/\b\w+'\w+\b|\b\w+\b/g, (word) => {
return word.substring(0, 1).toLocaleUpperCase() + word.substring(1)
})
console.log(newStr)
}
titleCase("i'm oyjh,i come from china")
- 统计一个字符串出现次数最多的字母
// 方法一:(数组方法)
function mostLatter (str) {
let arr = new String(str).split('').sort() // 转化为顺序数组
let newArr = []
let index = 0
for (let i = 0; i < arr.length; i++) { // 通过循环将相同的字母分成同一个数组元素
if (arr[i] === arr[i + 1]) {
continue
} else {
newArr.push(arr.slice(index,i + 1))
index = i + 1
}
}
let longArr = []
newArr.sort((a, b) => b.length - a.length) // 将相同字母数组组成的新数组的按各自长度从大到小排序
for (let j = 0;j < newArr.length;j++) {
if (newArr[0].length === newArr[j].length) {
longArr.push(...new Set(newArr[j])) // 去掉重复的字母数组内重复的数字
}
}
console.log(longArr.join(' '))
}
mostLatter('sadadhvajsdajhadhhasghsjssiljlywgj')
// 方法二:(正则)
function mostLatter(str) {
var arr = new String(str).split('') // 转换为数组
arr.sort() // 对数组进行排序
str = arr.join('') // 转换为字符串
var re = /(\w)\1+/g // 将相同的内容分割为一组
var value = ''
var num = 0
str.replace(re,function ($0, $1) { // replace 字符串替换 re规定字符串要替换的模式 $0父级,$1 第一个孩子
if ($0.length > num) {
num = $0.length
value = $1
}
})
console.log('最多的字符:'+value+',个数:'+num)
}
mostLatter('sadadhvajsdajhadhhasghsjssiljlywgj')
- 常见的一些排序算法?
冒泡排序:
var arr = [3,5,1,6,8,2,9,7,4]
function maopao (arr) {
for (let i = 0; i < arr.length; i++) { // 选择第一个数字进行冒泡
for(let j = 0; j < arr.length; j++) { // 将第一个数字一直交换到最后比他
if (arr[j] > arr[j+1]) {
let temp = arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
}
}
}
console.log(arr)
}
maopao(arr)
快速排序:
var arr = [3,5,1,6,8,2,9,7,4]
function kuaisu (arr) {
if(arr.length<=1){ //如果数组中只有一位数,返回数组
return arr;
}
var mNumIndex = Math.floor(arr.length/2); //取基准值的下标
var mNum = arr.splice([mNumIndex],1)[0]; //取基准值
var left = []; //左边数组
var right = []; //右边数组
for(var i=0;i<arr.length;i++){
if(arr[i]<mNum){ //如果数组小于基准值,放在左边数组
left.push(arr[i]);
}else{ ///否则
right.push(arr[i]);
}
}
return kuaisu(left).concat([mNum],kuaisu(right)) //输出左边数组+基准值+右边数组
}
console.log(kuaisu(arr))
选择排序:
var arr = [3,5,1,6,8,2,9,7,4]
function xuanze (arr) {
var len = arr.length
var minIndex, temp
for (var i = 0; i < len - 1; i++) {
minIndex = i
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { //寻找最小的数
minIndex = j //将最小数的索引保存
}
}
temp = arr[i]
arr[i] = arr[minIndex]
arr[minIndex] = temp
}
console.log(arr)
}
xuanze(arr)
- 找出一个数组中的最大差值
var arr = [-3,3,5,-1,-9,10,7,4,-13]
function max (arr) {
var newArr = []
arr.forEach(element => {
newArr.push(Math.abs(element))
})
newArr.sort((a, b) => a - b)
console.log(newArr.pop() - newArr.shift())
}
max(arr)
- 随机生成指定长度的字符串
function randomStr(len) {
let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'
let newStr = ''
for(let i = 0; i < len; i++){
let rand = parseInt(Math.random() * str.length)
newStr += str.substr(rand, 1)
}
console.log(newStr)
}
randomStr(7)
- 给定一个二维数组将其中每个数组的每个值拆分和其余剩下的数组组成一个新数组,输出新组成的所有数组
如输入[[1,2],[3,4],[5,6]]
输出:
[1, 3, 4]
[1, 5, 6]
[2, 3, 4]
[2, 5, 6]
[3, 1, 2]
[3, 5, 6]
[4, 1, 2]
[4, 5, 6]
[5, 1, 2]
[5, 3, 4]
[6, 1, 2]
[6, 3, 4]
function permutation(arr) {
let newArr = []
arr.forEach(element => {
ar = [...arr] // 深拷贝数组
ar.splice(ar.indexOf(element),1) // 删除二维数组中拆分的那个数组
for (let i = 0; i < element.length; i++) { // 一重循环遍历拆分的数组
for(let j = 0; j < ar.length; j++) { // 二重循环遍历其他的数组
newArr.push(element.slice(i,i+1).concat(...ar[j])) // 将拆分的各数组元素和剩下的数组组成一个新数组
}
}
});
console.log(newArr)
}
var arr = [[1,2,4],[3,4],[5,6]]
permutation(arr)
- 输出一个二维数组的全排列组合
如输入[[1,2],[3,4],[5,6]]
输出:
[ 1, 3, 5 ]
[ 1, 3, 6 ]
[ 1, 4, 5 ]
[ 1, 4, 6 ]
[ 2, 3, 5 ]
[ 2, 3, 6 ]
[ 2, 4, 5 ]
[ 2, 4, 6 ]
// arr为传入数组, index为二维数组开始下标,newArr为中间结果
function fullPermutation(arr, index, newArr) {
for (let i = 0; i < arr[index].length; i++) {
if (index === 0) {
newArr = []
}
if (index < arr.length) {
_newArr = [...newArr]
_newArr.push(arr[index][i])
if (index === arr.length - 1) {
console.log(_newArr)
} else {
fullPermutation(arr, index + 1, _newArr)
}
}
}
}
var arr = [[1,2],[3,4],[5,6]]
fullPermutation(arr,0)
此题,暂留,日后解决。
- 在不使用临时变量的情况下交换两个数字?
// 方法一 (加减运算)
function swap(a,b){
b = b-a
a = a+b
b = a-b
}
// 方法二(位运算)
function swap(a,b){
a = a^b
b = a^b
a = a^b
}
- 未完待续