LOADING

算法题

2022/1/23

判断一个单词是否是回文

// 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的。比如”level”

function checkHuiWen(str){
    return str == str.split('').reverse().join('')
}

// 比如输入: [1,13,24,11,11,14,1,2]
// 输出: [1,13,24,11,14,2]
// 需要去掉重复的 11 和 1 这两个元素。

//双循环
function arrUnique0(arr){
    let newArr = []
    for(let i=0,l=arr.length;i<l;i++){
        let key = true
        for(let j=0,l=newArr.length;j<l;j++){
            if(arr[i] == newArr[j]){
                key = false
            }
        }
        if(key){
            newArr.push(arr[i])
        }
    }
    return newArr
}


//indexof判断
//对象属性唯一性判断
function arrUnique2(arr){
    let newArr = []
    for(let i=0,l=arr.length;i<l;i++){
        if(newArr.indexOf(arr[i]) == -1){
            newArr.push(arr[i])
        }
    }

    return newArr
}

创建一个数组含有 100 个值为 0 元素

let arr = new Array(100)
arr.join('0').split('')

删除数组的第二项和第三项,再将最后一个元素压入数组头部

arr.splice(1,2)
arr.unshift(arr.pop())

随机获取数组中的元素

function getRandomFormArr(arr){
    return arr[Math.floor(Math.random()*arr.length)]
}

随机选取 5-105 中的 10 个不重复随机整数,然后按从小到大排序

function getNum(){
    let arr = []
    for(let i=5;i<=105;i++){
        arr.push(i)
    }
    return arr.sort(function(a,b){return Math.random()>0.5}).slice(0,10).sort(function(a,b){return a-b});
}

获取数组元素最大差值

//[2,4,6,9]返回 7

function getMaxProfit(arr){
    return Math.max.apply(Math,arr) - Math.min.apply(Math,arr)
}

深度克隆对象

function cloneObj(obj){
    let str, newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== 'object'){
        return obj;
    } else if(window.JSON){
        str = JSON.stringify(obj), //系列化对象
        newobj = JSON.parse(str); //还原
    } else {
        for(var i in obj){
            newobj[i] = typeof obj[i] === 'object' ?
            cloneObj(obj[i]) : obj[i];
        }
    }
    return newobj;
}

统计字符串出现次数最多的字母

function getMaxWord(str){
    let obj = {}
    for(let i in str){
        let word = str[i]
        if(obj[word]){
            obj[word]++
        }else{
            obj[word] = 1
        }
    }

    return  (function(obj){
                let maxWord = ''
                let maxTimes = 1
                for(let i in obj){
                    if(obj[i] > maxTimes){
                        maxWord = i
                        maxTimes = obj[i]
                    }
                }
                return maxWord
            })(obj)

}

实现 getType 获取数据类型

function getType(a){
    if(a === null)return 'null'
    return Object.prototype.toString.call(a).slice(8,-1).toLowerCase()
}

url 参数解析为对象

//a.html?a=1&b=2 返回{a:1,b:2}

function getUrlParam(urlStr){
    let url = urlStr || window.location.href
    if(url.indexOf('?') == -1)return null

    let arr = url.split('?')[1].split('&')
    let obj = {}
    for(let i in arr){
        let _arr = arr[i].split('=')
        obj[_arr[0]] = _arr[1]
    }
    return obj
}

创建“原生”(native)方法

//给字符串对象定义一个 repeatify 功能。当传入一个整数 n 时,它会返回重复 n 次字符串的结果

String.prototype.repeatify = function(n){
    return (new Array(n+1)).join(this)
}

实现冒泡排序

function mppx(arr){
    for(let i=0,l=arr.length-1;i<l;i++){
        for(let j=0;j<arr.length-i-1;j++){
            if(arr[j] > arr[j+1]){
                let a = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = a
            }
        }
    }
}

//优化版
function mppx(arr){
    for(let i=0,l=arr.length-1;i<l;i++){
        let key = 0
        for(let j=0;j<arr.length-i-1;j++){
            if(arr[j] > arr[j+1]){
                let a = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = a
                key = 1
            }
        }
        if(key == 0)return
    }
}

实现快速排序

function kspx(arr){
    if (arr.length <= 1) { return arr }
    let middleVal = arr.splice(Math.floor(arr.length/2),1)[0]
    let left = [],right = []
    for(let i in arr){
        if(arr[i] < middleVal){
            left.push(arr[i])
        }else{
            right.push(arr[i])
        }
    }
    return kspx(left).concat(middleVal,kspx(right))
}

实现二分查找

//传递一个已排序数组和值,通过二分搜索返回该值在数组中的索引

function efcz(arr,val){
    let low = 0
    let high = arr.length
    while(low < high){
        let mid = parseInt((high + low) / 2);
        if(val < arr[mid]){
            high = mid
        }else if(val > arr[mid]){
            low = mid
        }else{
            return mid
        }
    }
    return -1
}

promise 红绿灯问题

//红灯三秒亮一次,绿灯一秒亮一次,黄灯两秒亮一次,如何让三个灯不断交替重复亮

function red(){
    console.log('red')
}

function green(){
    console.log('green')
}

function yellow(){
    console.log('yellow')
}

事件队列实现

var event = {
    tasks : [],
    push : function(fn){
        this.tasks.push(fn)
        return this
    },
    go : function(){
        let fn = this.tasks.shift()
        fn && fn()
    }
}

//延时执行fn
function sleep(fn,time){
    setTimeout(function(){
        fn()
        event.go()
    },time)
}

function show(){
    event.push(function(){
        sleep(red,3000)
    }).push(function(){
        sleep(green,2000)
    }).push(function(){
        sleep(yellow,1000)
    }).push(function(){
        show()
    }).go()
}

promise 实现

function doPromise(fn,time){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            fn()
            resolve()
        },time)
    })
}

function show(){
    doPromise(red,3000).then(function(){
        return doPromise(green,2000)
    }).then(function(){
        return doPromise(yellow,1000)
    }).then(function(){
        show()
    })
}

不借助临时变量,进行两个整数的交换

//方法一 ES6
var a = 1, b = 2;
[a,b] = [b,a];
console.log(a,b)

统计一个字符串出现最多的字母:给出一段英文连续的英文字符窜,找出重复出现次数最多的字母。

str.charAt(i) //获取字符串第i个字符

function findMaxDuplicateChar(str) {
 if(str.length == 1) {
  return str;
 }
 let charObj = {};
 for(let i=0;i<str.length;i++) {
  if(!charObj[str.charAt(i)]) {
   charObj[str.charAt(i)] = 1;
  }
  else{
   charObj[str.charAt(i)] += 1;
  }
 }
 let maxChar = '',
   maxValue = 1;
 for(var k in charObj) {
  if(charObj[k] >= maxValue) {
   maxChar = k;
   maxValue = charObj[k];
  }
 }
 return maxChar;
}

斐波那契数列:1、1、2、3、5、8、13、21。输入 n,输出数列中第 n 位数的值。

function fn(n){
   if(n<=2){
        return 1;
   }
   return fn(n-1)+fn(n-2);
 }
console.log(fn(7)) //13

用 js 实现二分查找:二分查找的前提是有序数组

function binarySearch(arr,target,start,end){
    var start = start || 0;
    var end = end || arr.length-1;
    var mid = parseInt((start+end)/2);
    if(target == arr[mid]){
             return mid
         }else if(target > arr[mid]){
             start = mid + 1;
             return binarySearch(arr,target,start,end);
         }else if(target < arr[mid]){
             end = mid - 1;
             return binarySearch(arr,target,start,end);
         }else{
             return -1;
    }
}
var arr = [1,2,4,6,8,9,11,34,67];
console.log(binarySearch(arr,11));

数组去重

方案一:

function uniq(array){
    var temp = [];
    for(var i = 0; i < array.length; i++) {
        //如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
        if(array.indexOf(array[i]) == i){
            temp.push(array[i])
        }
    }
    return temp;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));

方案二:

var arr = [2,4,7,3,5,2,8,7];
var setArr = new Set(arr);
var newArr = Array.from(setArr);
Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。

方案三:

var arr =[1,2,2,4,5,4,11,6];
function fn(arr){
    var a=arr;
    for(var i=0;i<a.length;i++){
       for(var j=a.length-1;j>i;j--){
           if(a[i]==a[j]){
                a.splice(j,1);
           }
       }
    }
    return a;
}
var s=fn(arr);
console.log(s);

方案四:

let unique = function(arr) {
  let hashTable = {};
  let data = [];
  for(let i=0,l=arr.length;i<l;i++) {
    if(!hashTable[arr[i]]) {//把值当做下标
      hashTable[arr[i]] = true;
      data.push(arr[i]);
    }
  }
  return data
}

方案五:

    const s3 = new Set(["a","a","b","b"]);
    console.log(s3.size)
    const ary = [...s3];
    console.log(ary)

查找字符串中的最长公共前缀

示例: 输入: [“flower”,“flow”,“flight”]
输出: “fl”

function getMaxAndIndex( arr ){
  var firstStr = arr[0], result = ''
  if(!arr.length)
      return result
  for(let i=0;i<firstStr.length;i++){
      for(let j=1;j<arr.length;j++){
        if(firstStr[i]!=arr[j][i]){
          return result
        }
      }
      result += firstStr[i]
  }
  return result
}

深度拷贝、浅度拷贝

浅拷贝方法

方法一:

        var obj = {
            id: 1,
            name: 'andy',
            msg: {
                age: 18
            }
        };
        var o = {};
        for (var k in obj) {
            // k 是属性名   obj[k] 属性值
            o[k] = obj[k];
        }

方法二:

        Object.assign(o, obj);

        var obj1 = {a: 1, b: 2};
        var obj2 = Object.assign({}, obj1);// 第一个参数必须是个空对象

浅拷贝修改一个对象的值以后,两个对象的值都会改变

  o.msg.age = 20;

深拷贝方法

        var obj = {
            id: 1,
            name: 'andy',
            msg: {
                age: 18
            },
            color: ['pink', 'red']
        };
        var o = {};

封装函数

        function deepCopy(newobj, oldobj) {
            for (var k in oldobj) { // 判断我们的属性值属于那种数据类型

                // 1. 获取属性值  oldobj[k]
                var item = oldobj[k];

                // 2. 判断这个值是否是数组
                if (item instanceof Array) {
                    newobj[k] = [];
                    deepCopy(newobj[k], item)
                }
                else if (item instanceof Object) {
                // 3. 判断这个值是否是对象
                    newobj[k] = {};
                    deepCopy(newobj[k], item)
                } else {
                // 4. 属于简单数据类型
                    newobj[k] = item;
                }
            }
        }
        deepCopy(o, obj);

方法二:

JSON.parse(JSON.stringify())

判断回文

function checkPalindrom(str) {
    return str == str.split('').reverse().join('');
}

随机生成指定长度的字符串

比如给定 长度 8 输出 4ldkfg9j

function getMaxStr(n) {
    let str ='abcdefghijklmnopqrstuvwxyz9876543210';
    var tmp=''
    for(let i=0;i<n;i++){
      tmp=tmp+str.charAt(Math.floor(Math.random()*str.length))
    }
    return tmp
 }

随机数

当我们需要获取指定范围(min,max)内的整数的时候,下面的代码非常适合。

function getRadomNum(min,max){
   return Math.floor(Math.random() * (max - min + 1)) + min;
}

对象转换为数组

目标效果:
obj = { 0: 'a', 1: 'b', 2: 'c' }
=>
ayy=['a','b','c']

1、Array.from(object)

注:
object 中必须有 length 属性,返回的数组长度取决于 length 长度
key 值必须是数值

var obj={
    0:'qian',
    1:'long',
    2:'chu',
    3:'tian',
    length:4
}
console.log(Array.from(obj))

2、Object.values(object)

注:与第一种不同的是不需要 length 属性,返回一个对象所有可枚举属性值

返回数组的成员顺序:

const obj = {100: 'a', 2: 'b', 7: 'c' };
Object.values(obj)
// ["b", "c", "a"]

3.使用 for…in…构建函数

function getObjectKeys(object) {//属性名
  let keys = []
  for(let property in object)
    keys.push(property)
    return keys
}
function getObjectValues(object) {//值名
  let values = []
  for(let property in object)
    values.push(object[property])
    return values
}

数组转换为对象

1.

var fruits = [“banana”, “apple”, “orange”, “watermelon”];
var fruitsObj = { …fruits };
console.log(fruitsObj);

2.

var list = {};
var arr = ["123","456","789"];
for (var key in arr) {
    list[key] = arr[key];
}

保留指定小数位

var num =4.345678;
num = num.toFixed(4); // 4.3457 第四位小数位以四舍五入计算

数组中嵌套对象的筛选

var s=[];
    users.forEach((val,index,arr)=>{
        var f=0;
        var u={};
        for(let key  in val){
            if(key=='age' && parseInt(val[key])>=18)
                    f++
            if(key=='sex' && val[key]=='male')
                    f++
        }
        if(f==2)
        {
            for(let key  in val){
                if(key!='sex')
                    u.key=val[key]
                }
            s.push(u)
        }
    })