web大前端复习——js常见算法题1

Q1 判断一个单词是否是回文?

回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。比如 mamam redivider .

很多人拿到这样的题目非常容易想到用for 将字符串颠倒字母顺序然后匹配就行了。其实重要的考察的就是对于reverse的实现。其实我们可以利用现成的函数,将字符串转换成数组,这个思路很重要,我们可以拥有更多的自由度去进行字符串的一些操作。

        function checkPalindrom(str) {

            return str == str.split('').reverse().join('');

        }

        console.log(checkPalindrom('mamam'));   //true

        console.log(checkPalindrom('banana'));  //false

split() 方法用于把一个字符串分割成字符串数组。

reverse() 方法用于颠倒数组中元素的顺序。

join() 方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。

Q2 去掉一组整型数组重复的值

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

主要考察个人对Object的使用,利用key来进行筛选。

let unique = function(arr) {

            let hashTable = {};

            let data = [];

            for(let i=0,l=arr.length;i

                if(!hashTable[arr[i]]) {

                    hashTable[arr[i]] = true;

                    data.push(arr[i]);

                }

            }

            return data

        }

        var arr=[1,13,24,11,11,14,1,2]

        console.log(unique(arr))    //[1, 13, 24, 11, 14, 2]

还有一种方法 利用ES6的Set

var arr=[1,13,24,11,11,14,1,2];

let uniqueES6= function(arr){

            return Array.from(new Set(arr))

        }

console.log(uniqueES6(arr))//[1, 13, 24, 11, 14, 2]

Q3 统计一个字符串出现最多的字母

给出一段英文连续的英文字符窜,找出重复出现次数最多的字母

比如: 输入:afjghdfraaaasdenas 输出 : a

前面出现过去重的算法,这里需要是统计重复次数。

function findMaxDuplicateChar(str){

            if(str.length == 1){

                return str

            }

            let charObj ={}

            for(let i=0;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;

        }

        console.log(findMaxDuplicateChar('gffhghjllyesdfffnmfffssssffffjjffff')) //f

Q4 排序算法

如果说到算法题目的话,应该大多都是比较开放的题目,不限定算法的实现,但是一定要求掌握其中的几种。

冒泡排序

插入排序

快速排序

选择排序

let arr = [4,6,32,11,5,667,39,56,78,2,42,7];

        /*冒泡排序*/

        function bubbleSort(arr){

            for(var i=0;i

                for(var j=0;j

                    if(arr[j]>arr[j+1]){

                        var temp = arr[j]

                        arr[j] = arr[j+1]

                        arr[j+1] = temp

                    }

                }

            }

            return arr

        }

        console.log(bubbleSort(arr))

        /*插入排序*/

        function insertionSort(array) {

            console.time('插入排序耗时:');

            for (var i = 1; i < array.length; i++) {

                var key = array[i];

                var j = i - 1;

                while ( array[j] > key) {

                    array[j + 1] = array[j];

                    j--;

                }

                array[j + 1] = key;

            }

            console.timeEnd('插入排序耗时:');

            return array;

        }

        console.log(insertionSort(arr));

        /*快速排序*/

        function quickSort(arr){

            //如果数组<=1,则直接返回

            if(arr.length<=1){return arr;}

            var pivotIndex=Math.floor(arr.length/2);

            //找基准,并把基准从原数组删除

            var pivot=arr.splice(pivotIndex,1)[0];

            //定义左右数组

            var left=[];

            var right=[];

            //比基准小的放在left,比基准大的放在right

            for(var i=0;i

                if(arr[i]<=pivot){

                    left.push(arr[i]);

                }

                else{

                    right.push(arr[i]);

                }

            }

            //递归

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

        }

        console.log(quickSort(arr))

        // 选择排序

        var arr = [8,3,9,12,45,23,4,89,48,63,27,53,56,98]

        function selectSort(arr){

            var len = arr.length

            for(var i= 0;i

                for(var j = i+1;j

                    if(arr[i]>arr[j]){

                        var temp = arr[i]

                        arr[i] = arr[j]

                        arr[j] = temp

                    }

                }

            }

            return arr

        }

        console.log(selectSort(arr))

        // 选择排序的思想是:把每一个数都与第一个数比较,如果小于第一个数,就把它们交换位置;这样一轮下来,最小的数就排到了最前面;重复n-1轮,就实现了选择排序

       // 选择排序和冒泡排序思想上有些相近

十大经典排序算法总结(java代码)

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

举例:输入 a = 2, b = 4 输出 a = 4, b =2

这种问题非常巧妙,需要大家跳出惯有的思维,利用 a , b进行置换。

主要是利用 + - 去进行运算,类似 a = a + ( b - a) 实际上等同于最后 的 a = b;

        let a=2 ,b=4

        function swap(a , b) {

            b = b - a;

            a = a + b;

            b = a - b;

            return [a,b];

        }

        console.log(swap(a , b));

Q6 使用canvas 绘制一个有限度的斐波那契数列的曲线

斐波那契数列曲线

数列长度限定在10.

斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列主要考察递归的调用。我们一般都知道定义

fibo[i] = fibo[i-1]+fibo[i-2];

var canvas = document.querySelector('canvas');

        canvas.width = 600;

        canvas.height = 480;

        var coor = {

            x: 300,

            y: 240,

        };

        var ctx = canvas.getContext('2d');

        function draw(r, n ,prevR) {

            if(n>2) {

                switch(n%4) {

                    case 0 :

                        coor.y = coor.y - 5 * prevR;

                        coor.y = coor.y + 5 * r;

                        break;

                    case 1 :

                        coor.x = coor.x + 5 * prevR;

                        coor.x = coor.x - 5 * r;

                        break;

                    case 2 :

                        coor.y = coor.y + 5 * prevR;

                        coor.y = coor.y - 5 * r;

                        break;

                    case 3 :

                        coor.x = coor.x - 5 * prevR;

                        coor.x = coor.x + 5 * r;

                        break;

                }

            }

            ctx.beginPath();

            ctx.arc(coor.x,coor.y,5*r,Math.PI*0.5*(n),Math.PI*0.5*(n-1),true);

            if(n>1) {

                switch(n%4) {

                    case 0 :

                        ctx.moveTo(coor.x - 5*r,coor.y);

                        break;

                    case 1 :

                        ctx.moveTo(coor.x,coor.y + 5*r);

                        break;

                    case 2 :

                        ctx.moveTo(coor.x + 5*r,coor.y);

                        break;

                    case 3 :

                        ctx.moveTo(coor.x,coor.y-5*r);

                        break;

                }

            }

            ctx.lineWidth = 1;

            ctx.strokeStyle = '#fff';

            ctx.stroke();

        }

        /*生成斐波那契数组的方法*/

        function getFibonacci(n) {

            var fibarr = [];

            var i = 0;

            while(i

                if(i<=1) {

                    fibarr.push(i);

                }else{

                    fibarr.push(fibarr[i-1] + fibarr[i-2])

                }

                i++;

            }

            return fibarr;

        }

        console.log(getFibonacci(10))  //[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

        var data = getFibonacci(10);

        for(var i = 0,l=data.length;i

            if(data[i]!=0) {

                draw(data[i],i,data[i-1]);

            }

        }

Q7 找出下列正数组的最大差值

比如: 输入 [10,5,11,7,8,9] 输出 6

这是通过一道题目去测试对于基本的数组的最大值的查找,很明显我们知道,最大差值肯定是一个数组中最大值与最小值的差。

        var arr = [16,5,111,7,21,9]

        function getMaxProfit(arr) {

            const item1 = Math.max.apply( null, arr );

            const item2 = Math.min.apply( null, arr );

            return item1 - item2;

        }

        console.log(getMaxProfit(arr)) //106

ES6的方法

        var arr = [16,5,111,7,21,9]

        //ES6

        function getMaxProfitES6(arr){

            const item1 = Math.max(...arr);

            const item2 = Math.min(...arr);

            return item1 - item2;

        }

        console.log(getMaxProfitES6(arr));

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

实现一个算法,随机生成指制定长度的字符窜。

比如:给定 长度 8 输出 4ldkfg9j

        function randomString(n) {

            let str = 'abcdefghijklmnopqrstuvwxyz9876543210';

            let tmp = '',

                l = str.length;

            for (let i = 0; i < n; i++) {

                tmp += str.charAt(Math.floor(Math.random() * l));

            }

            return tmp;

        }

        console.log(randomString(8))

Q9 计算一个整数的阶乘

        function factorialize(num) {

            if(num<1){

                return 1;

            }else{

                return num*factorialize(num-1);

            }

        }

        console.log(factorialize(5));   //120

Q10 找到提供的句子中最长的单词,并计算它的长度

        function findLongestWord(str) {

            //转化成数组

            var astr=str.split( " " );

            //对数组中每个元素的字符串长度进行比较,按照字符串长度由大至小排列数组顺序。

            var bstr=astr.sort(function(a,b){

                return b.length-a.length;

            });

            //取出数组中第一个元素(也就是最大长度的字符串)

            console.log(bstr[0])       //jumped

            var lenMax= bstr[0].length;

            //返回长度值

            return lenMax;

        }

        console.log(findLongestWord("The quick brown fox jumped over the lazy dog"));//6

array.sort()方法默认是升序排序,如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:

若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。

若 a 等于 b,则返回 0。

若 a 大于 b,则返回一个大于 0 的值。

简单点:比较函数两个参数a和b,返回a-b升序,返回b-a降序

Q11 确保字符串的每个单词首字母都大写,其余部分小写。

        function titleCase(str) {

            var astr=str.toLowerCase().split(" ");

            for(var i=0 ; i

                astr[i]=astr[i][0].toUpperCase()+astr[i].substring(1,astr[i].length);

            }

            var string=astr.join(" ");

            return string;

        }

        console.log(titleCase("I'm a little tea pot"));//结果:I'm A Little Tea Pot

Q12 找出4个小数组中最大值,组成一个新数组

        function largestOfFour(arr) {

            var newArr=[];

            for(i=0;i

                arr[i].sort(function(a,b){

                    return b-a;

                });

                newArr.push(arr[i][0]);

            }

            return newArr;

        }

        console.log(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]));   //[5,27,39,1001]

Q13 比较两个数组,然后返回一个新数组,该数组的元素为两个给定数组中所有独有的数组元素。换言之,返回两个数组的差异。

方法一:

        function diff(arr1, arr2) {

            var newArr = [];

            //过滤数组1中与数组2相等的项

            var arr1Filtered=arr1.filter(function(num){

                for(var i=0; i

                    if(num==arr2[i]){

                        return false;

                    }

                }

                return true;

            });

            //过滤数组2中与数组1相等的项

            var arr2Filtered=arr2.filter(function(num){

                for(var i=0; i

                    if(num==arr1[i]){

                        return false;

                    }

                }

                return true;

            });

            //连接两个数组

            newArr=arr1Filtered.concat(arr2Filtered);

            return newArr;

        }

        var arr1 = [1, "calf", 3, "piglet"],

            arr2 = [1, "calf", 3, 4]

        console.log(diff(arr1, arr2));  // ["piglet", 4]

方法二:

        var arr1 = [1, "calf", 3, "piglet"],

        arr2 = [1, "calf", 3, 4]

        function fn(arr1,arr2){

            var newArr = []

            var arr1Filtered = arr1.filter(function(num){

                if(arr2.indexOf(num)!=-1){

                    return false

                }

                return true

            })

            var arr2Filtered = arr2.filter(function(num){

                if(arr1.indexOf(num)!=-1){

                    return false

                }

                return true

            })

            return arr1Filtered.concat(arr2Filtered)

        }

        console.log(fn(arr1,arr2))

Q14 写一个 function,传入两个或两个以上的数组,返回一个以给定的原始数组排序的不包含重复值的新数组。

说明:所有数组中的所有值都应该以原始顺序被包含在内,但是在最终的数组中不包含重复值。

如:unite([1, 3, 2], [5, 2, 1, 4], [2, 1]) 应该返回 [1, 3, 2, 5, 4]。

unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) 应该返回 [1, 2, 3, 5, 4, 6, 7, 8]。

方法一:

        function unite(arr1, arr2, arr3) {

            for(var j=1; j

                //过滤掉第j个数组中已经在前面出现过的值

                var filteredArr=arguments[j].filter(function(num){

                    for(var i=0; i

                        if(arr1[i]==num){

                            return false;

                        }

                    }

                    return true;

                });

                arr1=arr1.concat(filteredArr);

            }

            return arr1;

        }

        console.log(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])); //[1,2,3,5,4,6,7,8]

方法二:

        function unite(){

            var arr = arguments[0]

            for(let i = 0;i

                var filterArr = arguments[i].filter(function(num){

                    if(arr.indexOf(num)!=-1){

                        return false

                    }

                    return true

                })

                arr= arr.concat(filterArr)

            }

            return arr

        }

        console.log(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]));

Q15 求小于等于给定数值的质数(素数)之和。

说明:只有 1 和它本身两个约数的数叫质数。例如,2 是质数,因为它只能被 1 和 2 整除。1 不是质数,因为它只能被自身整除。给定的数不一定是质数。

如:sumPrimes(10) 应该返回 17。

        function sumPrimes(num) {

            //将所有小于等于num的质数放进一个数组

            var arr=[];

            //1不是质数,从2开始循环,需算上num

            for(var i=2; i<=num; i++){

                var j=2;

                //判断i能否被从2开始的数整除

                while(i%j!==0){

                    j++;

                }

                //判断这个数是不是自身,是则加进数组

                if(i==j){

                    arr.push(i);

                }

            }

            //对数组求和

            var result=arr.reduce(function (a,b){return a+b;});

            return result;

        }

        console.log(sumPrimes(10))  ///17

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

reduce() 可以作为一个高阶函数,用于函数的 compose。

注意: reduce() 对于空数组是不会执行回调函数的。

另外一种写法

        function sumFun(num){

          let sum=0

          for(let i=2;i<=num;i++){

            var j= 2

            while(i%j !==0){

              j++

            }

            if(j==i){

              sum+=j

            }

          }

          return sum

        }

        console.log(sumFun(11)) //18

方法三

    function getPrimes(n){

        var arr = []

        for(var i=2;i<=n;i++){

            var flag = true

            for(var j = 2;j<=Math.sqrt(i);j++){

                if(i%j==0){

                    flag = false

                    break

                }

            }

            if(flag){

                arr.push(i)

            }

        }

        //对数组求和

        var result=arr.reduce(function (a,b){return a+b;});

        return result

    }

方法四

    function getPrimes(n){

        var prime = []

        var arr = []

        for(var i = 2;i<=n;i++){

            if(!prime[i]){

                arr.push(i)

                for (var j = i; j*i <=n; j++) {

                    prime[j*i]=true;

                }

            }

        }

        //对数组求和

        var result=arr.reduce(function (a,b){return a+b;});

        return result

    }

Q16 写一个 function,它浏览数组(第一个参数)并返回数组中第一个通过某种方法(第二个参数)验证的元素。

如:find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }) 应该返回 8。

find([1, 3, 5, 9], function(num) { return num % 2 === 0; }) 应该返回 undefined。

        function find(arr, func) {

            var newArr=arr.filter(func);

            return newArr[0];

        }

        console.log(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; })) //8

Q17 对嵌套的数组进行扁平化处理。你必须考虑到不同层级的嵌套。

如:steamroller([1, [2], [3, [[4]]]]) 应该返回 [1, 2, 3, 4]。

steamroller([1, [], [3, [[4]]]]) 应该返回 [1, 3, 4]。

steamroller([1, {}, [3, [[4]]]]) 应该返回 [1, {}, 3, 4]。

1、

        function steamroller(arr) {

            var newArr=[];

            for(var i=0; i

                if(!Array.isArray(arr[i])){

                    newArr.push(arr[i]);

                }else{

                    newArr=newArr.concat(steamroller(arr[i]));

                }

            }

            return newArr;

        }

        console.log(steamroller([1, {}, [3, [[4]]]]))   //[1, {}, 3, 4]

此题的解法是在一个for循环中使用了递归,在for循环中使用递归时,不会影响for循环的进程。

2、另外一种方法:

      function flatten(arr){

        while(arr.some(item=>Array.isArray(item))){

          arr = [].concat(...arr)

        }

        return arr;

      }

      console.log(flatten([1, {}, [3, [[4]]]]));//[1, 2, 3]

some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。

some() 方法会依次执行数组的每个元素:

如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。

如果没有满足条件的元素,则返回false。

注意:some() 不会对空数组进行检测。

注意:some() 不会改变原始数组。

3、es6新增的数组实例方法flat()

[1, 2, [3, 4]].flat()

// [1, 2, 3, 4]

flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。

[1, 2, [3, [4, 5]]].flat()

// [1, 2, 3, [4, 5]]

[1, 2, [3, [4, 5]]].flat(2)

// [1, 2, 3, 4, 5]

如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。

[1, [2, [3]]].flat(Infinity)

// [1, 2, 3]

如果原数组有空位,flat()方法会跳过空位。

[1, 2, , 4, 5].flat()

// [1, 2, 4, 5]

4、如果数组中元素都是字符串,可以利用数组toString()方法

例如:['a',[b],c,[[d],e,[f,[g,h]]]]

   var arr= ['a',[`b`],`c`,[[`d`],`e`,[`f`,[`g`,`h`]]]]

   console.log(arr.toString().split(','))

Q18 二分查找

        function binary_search(arr, key) {

            var low = 0,

                high = arr.length - 1;

            while(low <= high){

                var mid = parseInt((high + low) / 2);

                if(key == arr[mid]){

                    return  mid;

                }else if(key > arr[mid]){

                    low = mid + 1;

                }else if(key < arr[mid]){

                    high = mid -1;

                }

            }

            return -1;

        };

        var arr=[2,4,6,9,11,25,28,36,44,47,67,76,79],

            key=36;

        console.log(binary_search(arr,key)) //7

因为二分查找每次排除掉一半的不适合值,所以对于n个元素的情况:

一次二分剩下:n/2

两次二分剩下:n/2/2 = n/4

……

m次二分剩下:n/(2^m)

在最坏情况下是在排除到只剩下最后一个值之后得到结果,所以为

n/(2^m)=1;

2^m=n;

所以时间复杂度为:log2(n)

作者:指尖跳动

链接:https://www.jianshu.com/p/2f38ac50c63a

来源:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(web大前端复习——js常见算法题1)