前端面试题 - 算法

// 1.限制最大请求
function asyncPool(list, limitCount, fun){
    let i=0; 
    let totalList = [];
    let excuteList = [];

    const queue = function(){
        if(totalList.length === limitCount){
            return Promise.resolve();
        }

        let p = Promise.resolve().then(() => {fun(list[i++], list);})
        totalList.push(p);

        let e = p.then(() => {excuteList.splice(excuteList.indexOf(e), 1)});
        excuteList.push(e);

        let r = excuteList.length >= limitCount ? Promise.race(excuteList) : Promise.resolve()

        return r.then(() => queue)

    }

    return queue.then(() => Promise.all(totalList))
}

// 方法二
function multiRequest(urls = [], maxNum) {
    // 请求总数量
    const len = urls.length;
    // 根据请求数量创建一个数组来保存请求的结果
    const result = new Array(len).fill(false);
    // 当前完成的数量
    let count = 0;

    return new Promise((resolve, reject) => {
        // 请求maxNum个
        while (count < maxNum) {
            next();
        }

        function next() {
            let current = count++;
            // 处理边界条件
            if (current >= len) {
                // 请求全部完成就将promise置为成功状态, 然后将result作为promise值返回
                !result.includes(false) && resolve(result);
                return;
            }
            const url = urls[current];
            console.log(`开始 ${current}`, new Date().toLocaleString());
            fetch(url)
                .then((res) => {
                    // 保存请求结果
                    result[current] = res;
                    console.log(`完成 ${current}`, new Date().toLocaleString());
                    // 请求没有全部完成, 就递归
                    if (current < len) {
                        next();
                    }
                })
                .catch((err) => {
                    console.log(`结束 ${current}`, new Date().toLocaleString());
                    result[current] = err;
                    // 请求没有全部完成, 就递归
                    if (current < len) {
                        next();
                    }
                });
        }
    });
}

// 2.找到最多重复字符
function findMaxDuplicateChar(str){
    if(str.length === 1){
        return [str, 1]
    }
    let object = {};
    for(let key of Object.keys(str)){
        const char = str[key];
        if(!object[char]){
            object[char] = 1;
        } else {
            object[char] = object[char] + 1;
        }
    }

    let maxChar = '';
    let maxCount = 0;
    for(let i of Object.keys(object)){
        if(object[i] > maxCount){
            maxChar = i;
            maxCount = object[i];
        }
    }

    return [maxChar, maxCount];
}

// 3.洗牌算法
function getMess(list){
    return list.sort(function(){
        Math.random() - 0.5;
    })
}

function getMess2(list){
    let resultList = [];
    let length = list.length;
    while(length){
        resultList.push(list.splice(Math.floor(Math.random() * length--), 1)[0]);
    }
    return resultList;
}

// 4.排序算法
// (1)冒泡
function bubbleSort(list){
    let length = list.length;
    for(let i=0; i < length; i++){
        for(let j=i+1; j < length; j++){
            if(list[i] > list[j]){
                let value = list[j];
                list[j] = list[i];
                list[i] = value;
            }
        }
    }
}

// (2)快速排序
function quickSort(list){

    if(list.length <= 1){
        return list;
    }
    
    let middleIndex = Match.floor((list.length-1)/2);
    let middleValue = list.splice(middleIndex, 1)[0];

    let left = [];
    let right = [];

    for(let key of Array.keys(list)){
        if(list[key] <= middleValue){
            left.push(list[key]);
        } else {
            right.push(list[key]);
        }
    }

    return quickSort(left).concat([middle], quickSort(right));
}

// (3)插入排序
let searchIndex = (arr, item) => {
    if(item < arr[0]){
        return 0;
    } 
    if(item > arr[arr.length - 1]){
        return arr.length;
    }
    let i=0;
    for(; i<arr.length; i++){
        if(arr[i] <= item && item <= arr[i+1]){
            break;
        }
    }
    return i+1;
}

let insertSort = arr => {
    if(arr.length === 0){
        return;
    }
    let resultList = [arr[0]];
    for(let i=1; i<arr.length; i++){
        let index = searchIndex(resultList, arr[i]);
        resultList.splice(index, 0, arr[i]);
    }
    return resultList;
}

// 5.斐波那契数列
let getFibonacci = n => {
    if(n <=1) return 1;
    let result = getFibonacci(n-1) + getFibonacci(n-2);
    return result;
}

// 尾递归
let getFibonacci1 = (n, ac1=1, ac2=1) => {
    if(n<=1) {return ac2};
    let result = getFibonacci1(n-1, ac2, ac1+ac2);
    return result;
}

// 6.生成1~100的数组
// (1)ES6
let arr = Array.from(Array(100), (value, index) => index + 1);

// (2)ES5
let arr1 = Array.prototype.map(Array(101).join('0').split(''), function(){
    return arguments[1]+1;
})

// 7.数组去重
// (1)Object
function unique(arr2){
    let obj = {};
    let resultList1 = [];
    for(let i=0; i<arr.length; i++){
        if(!obj[arr2[i]]){
            obj[arr2[i]] = true;
            resultList1.push(obj[arr2[i]]);
        }
    }
    return resultList1;
}

// (2)filter
function unique2(arr3){
    return arr3.filter((item, index) => {
        if(arr3.indexOf(item) !== index){
            return false;
        }
        return true;
    })
}

// (3)Set
let resultList = Array.form(new Set(arr4))

// (4)new array
function unique3(arr4){
    let rstList = [];
    arr4.forEach(element => {
        if(rstList.indexOf(element) === -1){
            rstList.push(element);
        }
    });
    return rstList;
}

// 8.二叉树高度
function h(node){
    return node === null ? 0 : (Math.max.call(h(node.left), h(node.right)) + 1);
}

// 9.千分位逗号
function numFormat(str){
    str = str.indexOf('.') !== -1 ? str.split('.')[0] : str;
    let reverseList = Array.from(str).reverse();
    let rstList = [];
    for(let i=0; i<reverseList.length; i++){
        if(i%3 === 0 && i > 0){
            rstList.push(',');
        } else {
            rstList.push(reverseList[i]);
        }
    }
    rstList.reverse()
    let rstStr = rstList.join('');
    rstStr = str.indexOf('.') !== -1 ? rstStr + str.split('.')[1] : rstStr;
    return rstStr;
}

// 10.大数字加减法
function bigData(a, b){
    if(a === '' || b === '' || escape(a).index('%u') !== -1 || escape(b).index('%u') !== -1){
        console.log('err');
        return ;
    }
    let numA = new Number(a);
    let numB = new Number(b);
    let numC = new Number(numA + numB).toLocaleString();
    let result = numC.replace(/,/g, ''); 
    return result;
}

// 11.最长公共子串
function getLongestStr(str1, str2){
    let result = '';
    if(str1.length < str2.length){
        [str1, str2] = [str2, str1];
    }
    for(let j=str1.length; j>0; j--){
        for(let i=0; i<str1.length - j; i++){
            let str1Part = str1.substring(i, j);
            if(str2.includes(str1Part)){
                result = str1Part;
                return result;
            }
        }
    }
    
}

// 12.最长连续数字
function findLongestNum(str){
    let rstList = [];
    let itemList = isNum(str[0]) ? [parseInt(str[0])] : [];
    for(let key of str){
        if(key > 0){
            if(isNum(str[key]) && (key < str.length - 1) && isNum(str[key - 1]) && (parseInt(str[key - 1]) + 1 === parseInt(str[key]))){
                itemList.push(parseInt(str[key]));
            } else {
                rstList.push(itemList);
                itemList = [];
            }
        }
    }

    let maxCount = 0;
    let resultStr = '';
    rstList.forEach(item => {
        if(item.length > maxCount){
            maxCount = item.length;
            resultStr = item.join('');
        }
    })

    return resultStr;

    function isNum(str1){
        if(parseInt(str1) >= 0 && parseInt(str1) < 10){
            return true;
        }
        return false;
    }
}

// 13.LCS动态规划求最长公共子序列
function getLongestSeq(ary1, ary2){
    ary1 = ary1.unshift("");
    ary2 = ary2.unshift("");
    const length1 = ary1.length; 
    const length2 = ary2.length;
    let t = [];
    for(let i=0; i<length1; i++){
        t[i] = [];
        for(let j=0; j<length2; j++){
            if(i == 0 || j == 0){
                t[i][j] = 0;
            }
            if(ary[i] === ary[j]){
                t[i][j] = t[i-1][j-1] + 1;
            } else {
                t[i][j] = Math.max(t[i][j-1], t[i-1][j]);
            }

        }
    }

    let n1 = length1 - 1;
    let n2 = length2 - 1;
    let result = [];
    while(n1>0 && n2>0){
        if(ary1[n1] == ary2[n2]){
            result.unshift(ary1[n1]);
            i--;
            j--;
        } else {
            if(t[i-1][j] > t[i][j-1]){
                i--;
            } else {
                j--;
            }
        }
    }

    return result;
}

// 14.柯里化
function curry(fn){
    let c = (...arguments) => (fn.length === arguments.length) ?
    fn(arguments) : (...arguments1) => c(...arguments, ...arguments1);
    return c;

    // return (a) => {
    //     return (b) => {
    //         return (c) => {
    //             fn(a*b*c);
    //         }
    //     }
    // }
}

// 15.反转二叉数
function invertTree(node){
    if(node !== null){
        [node.left, node.right] = [node.right, node.left];
        invertTree(node.left);
        invertTree(node.right);
    }
    return node;
}

// 16.贪心算法解决背包问题
let number = ['A', 'B', 'C', 'D'];
let weights = [20, 15,23,30];
let values = [50, 200, 15, 30];
let capacity = 32;

function greedy(weighst, values, capacity){
    let rest = capacity;
    let num = 0;
    let sortAry = [];   
    weights.forEach((item, index) => {
        sortAry.push({
            weight: item,
            value: values[index],
            radio: values[index] / item
        })
    })
    sortAry.sort(function(a, b){a.radio > b.radio});
    let result = 0;
    sortAry.forEach(item => {
        num = Math.floor(rest / item.weight);
        rest -= num * item.weight;
        result = num * item.value;
    })
    return result;
}

// 17.找到一个数组中的两个元素之和为S的两个元素。
function findNumbersWithSum(arr, s){
    for(let i=0; i<arr.length / 2; i++){
        if(arr.indexOf(s - arr[i], i+1) !== -1){
            return [arr[i], arr.indexOf(s - arr[i])];
        }
    }
    return [];
}

// 18.两个升序数组合并成一个
function mergeSort(arr1, arr2){
    let resultList = [];
    let i=0, j=0, p=0, length1 = arr1.length, length2 = arr2.length;
    while(i < length1 || j < length2){
        if(i < length1 && j < length2){
            resultList[p++] = arr1[i] < arr2[j] ? arr1[i++] : arr2[j++];
        } else if(i<length1){
            resultList[p++] = arr1[i++];
        } else {
            resultList[p++] = arr2[j++];
        }
    }
    return resultList;
}

// 19.判断一个链表是否有环
// (1) set
function hasCircle(node){
    let s = new Set();
    while(node){
        if(s.has(node)){
            console.log('有环 node=', node);
            return;
        }
        s.add(node);
        node = node.next();
    }
    console.log('无环');
    return;
}

// (2) visited
function hasCircle1(node){
    while(node){
        if(node.visit){
            console.log('有环');
            return;
        }
        node.visit = true;
        node = node.next();
    }
    console.log('无环');
}

// (3) 双指针
function hasCircle2(node){
    let quickNode = node.next().next();
    let slowNode = node.next();

    while(quickNode && slowNode){
        if(quickNode === slowNode){
            return '有环'
        }
        quickNode = quickNode.next().next();
        slowNode = node.next();
    }
    return '无环';
}

// 20.判读环的入口
function entry(node){
    let quickNode = node.next().next();
    let slowNode = node.next();

    while(quickNode && slowNode){
        if(quickNode === slowNode){
            quickNode = node;
            while(quickNode && slowNode){
                if(quickNode === slowNode){
                    return quickNode;
                }
                quickNode = quickNode.next();
                slowNode = slowNode.next();
            }
            
        }
        quickNode = quickNode.next().next();
        slowNode = node.next();
    }

    return null;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容