前端面试算法题总结

1.回文判断:


    var str = 'resiviser';
    function reserve(str) {
      return str === str.split('').reverse().join('');
    }
 

2.数组去重


  function unique(arr) {
      const container = {};
      const newArr = [];
      for(let i = 0,len = arr.length;i < len; i++) {
        if (!container[arr[i]]) {
          container[arr[i]] = true;
          newArr.push(arr[i]);
        }
      }
      return newArr;
    }

3.尾递归阶乘


    function factorial(num) {
      if(num <= 1) return 1;
      return num * factorial(num - 1);
    }

4.快排

function quickSort (arr) {
      if (arr.length <= 1) return arr;
      let middleIndex = Math.floor(arr.length/2);
      let middle = arr.splice(middleIndex, 1)[0];
      let left = [];
      let right = [];
      for(let i = 0,len = arr.length; i < len; i++){
        if(arr[i] < middle) {
          left.push(arr[i]);
        } else {
          right.push(arr[i]);
        }
        // console.log(left, right)
      }
      // console.log('------------')
      return quickSort(left).concat([middle] ,quickSort(right));
    }
    console.log(quickSort([2,3,1,4,6,5,9,8]));

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

function findMoreLetter(str) {
      let container = {};
      var maxValue = 0;
      let maxKey = '';
      str = str.split('');
      for(let i = 0,len = str.length; i < len; i++) {
        if(!container[str[i]]) {
          container[str[i]] = 1;
        } else {
          ++ container[str[i]];
        }
      }
      Object.keys(container).forEach((key) => {
        if (container[key] >= maxValue) {
          maxValue = container[key];
          maxKey = key;
        } 
      });
      return maxKey + '一共出现了' + maxValue;
    }
    console.log(findMoreLetter('asdfsasdasfas'));

6.链表反转 

方法一:

function printListFromTailToHead(head)
{
    let arr = [];
    let start = head;
    while(start){
        arr.push(start.val);
        start = start.next;
    }
    return arr.reverse();
}

方法二:

function rvs(H){
		if(H==null||H.next==null)
			return H;
		var newHead=rvs(H.next);
		H.next.next=H;
		H.next=null;
		return newHead;
}
function reverse(){
		var H=this.head;
		this.head=rvs(H);
	}

//插入节点的方法
function insert(node){
		var newNode=new Node(node);
		if(this.head==null){
			this.head=newNode;
		}else{
			var current=this.head;
			while(current.next!==null){
				current=current.next;
			}
			current.next=newNode;
		}
		this.length++;
	}

7.点击a标签,弹出对应的序号(闭包,立即执行函数

for(var i=0;i<10;i++){

            (function(i){

                var a=document.createElement('a');

                a.innerHTML=i+'<br>';

                document.body.appendChild(a);

                a.addEventListener('click',function(e){
                    e.preventDefault();  //取消默认事件,指a标签
                    alert(i);
                });

            })(i);

        }

8.每个三个数字加一个“,”

function fun(str){
	var num=str.split(".")[0];
	var arr=[];
	var result="";
	var length=num.length;
	arr=num.split("").reverse();
	console.log(arr);
	for(var i=0;i<arr.length;i++){
		if((i+1)%3==0&&i!==length-1){
			result+=arr[i]+",";
		}
		else{
			result+=arr[i];
		}
	}
	result=result.split("").reverse().join("");
	result+="."+str.split(".")[1];
	console.log(result);
}
fun("12993456789123.456789123");

9.数组实现斐波那契

int f(int n){
	int res;
	int a[n];
	a[0]=1;
	a[1]=1;
	a[2]=2;
	if(n<=2) res=a[n];
	if(n>2){
		for(int i=3;i<=n;i++){
			a[i]=a[i-1]+a[i-2];
			printf("%d\n",a[i]);
		}
		res=a[n];
	}
	return res;
} 

int main(){
	int n,res;
	scanf("%d",&n);
	res=f(n);
	printf("%d",res);
}

10.求最长无重复子串

 var lengthOfLongestSubstring = function(s) {
         var res = 0; // 用于存放当前最长无重复子串的长度
         var str = ""; // 用于存放无重复子串
         var len = s.length;
         for(var i = 0; i < len; i++) {
             var char = s.charAt(i);
             var index = str.indexOf(char);
             if(index === -1) {
                 str += char;
                 res = res < str.length ? str.length : res;
             } else {
                 str = str.substr(index + 1) + char;
             }
         }
         return str;
     };

11.找数组中连续最大子数组之和

/*
     遍历数组,遇到负的和则放弃之前的结果,重新积累,这期间保留最大值;
    用sum记录最终返回的最大和,用tempsum记录累计值;
    对于数组中的一个数array[i],若其左边的累加和非负,那么加上array[i];
    判断此时的tempsum是否大于sum,若大于此时的sum,则用sum记录下来。
    */
     var findBiggestSum=function(arr){
         if(arr.length<0) return 0;
         var sum=arr[0],tempSum=arr[0];//注意初始值 不能设为0 防止数组全是负数
         for(var i=1;i<arr.length;i++){
             tempSum=(tempSum<0)?arr[i]:tempSum+arr[i]
             sum=tempSum>sum?tempSum:sum;
         }
         return sum;
     }
     findBiggestSum([-10,-5,-3,-7,-9]);

12.对数组对象按照属性排序,number升序,string按照ascll码排序

 function sortNumber(propName){
         return function(obj1,obj2){
         return obj1[propName]-obj2[propName]
         };

     }
     function sortString(data){
         var newArray=[];
         for(var i=0;i<data.length;i++){
             newArray[i]=data[i].b;
         }
         newArray.sort();
         var newData=[];
         var k=0;
         for(var i=0;i<newArray.length;i++){
             for(var j=0;j<data.length;j++){
                 if(newArray[i]===data[j].b){
                     newData[k]=(data[j]);
                     k++;
                 }
             }
         }
         return newData;
     }
     var data = [{a:1,b:"d"},{a:0,b:"a"},{a:3,b:"k"},{a:2,b:"c"}];
     sortString(data);
     
     data.sort(sortNumber('a'))

13.数组拍平

递归调用:

 function fn(arr){
         let arr1 = []
         arr.forEach((val)=>{
             if(val instanceof Array){
                 arr1 = arr1.concat(fn(val))
             }else{
                 arr1.push(val)
             }
         })
         return arr1
     }

flat:

 arr.flat(Infinity)

reduce:

function fn(arr){
         return arr.reduce((prev,cur)=>{
             return prev.concat(Array.isArray(cur)?fn(cur):cur)
         },[])
     }

toString:

 var arr=[1,2,[3,4,5,[6,7,8],9],10,[11,12]];
     function fn(arr){
         var newArr=arr.toString().split(",").map((val)=>{
             return parseInt(val)
         })
         console.log(newArr)
     }
     fn(arr);

解构赋值:

function fn(arr){
         while (arr.some(Array.isArray)) {
             arr = [].concat(...arr);
         }
         console.log(arr);
     }

14.二叉树创建以及遍历

function Node(data,left,right){
         this.data=data;
         this.left=left;
         this.right=right;
     }
     Node.prototype.show=function(){
         return this.data;
     }
     function BST(){
         this.root=null;
     }
     BST.prototype.insert=function(data){
         var node=new Node(data,null,null);
         if(this.root===null){
             this.root=node;
         }
         else{
             var current=this.root;
             var parent;
             while(true){
                 parent=current;
                 if(data<current.data){
                     current=current.left;
                     if(current===null){
                         parent.left=node;
                         break;
                     }
                 }
                 else{
                     current=current.right;
                     if(current===null){
                         parent.right=node;
                         break;
                     }
                 }
             }
         }
     }
    //前序遍历
     BST.prototype.prevOrder=function(node){
         if(node){
             console.log(node.show()+" ");
             this.prevOrder(node.left);
             this.prevOrder(node.right);
            
         }
          /*非递归
         var stack=[];
         var res=[];

         stack.push(root);
         if(root===null){
             return;
         }
         while(stack.length>0){
             var node=stack.pop()
             res.push(node.data);
             if(node.right){
                 stack.push(node.right)
             }
             if(node.left){
                 stack.push(node.left)
             }
         }
         console.log(res)*/
//中序
/*let nodestack = [];
    let res = [];
    if(root===null){
       return [];
    }
    while(root!==null||nodestack.length>0){
        while(root!==null){
            nodestack.push(root);
            root = root.left;
        }
        root = nodestack.pop();
        res.push(root.val);
        root=root.right;
    }
*/
//后序
/*var postorderTraversal = function(root) {
    let nodestack = [];
    let res = [];
    if(root===null){
        return [];
    }
    nodestack.push(root);
    while(nodestack.length>0){
        let node = nodestack.pop();
        res.unshift(node.val);
        if(node.left){
            nodestack.push(node.left);
        }
        if(node.right){
            nodestack.push(node.right);
        }
    }
    return res;
};*/
     }
     var nums = [10,3,18,2,4,13,21,9,8,9];
     var bst=new BST();
     for(var i=0;i<nums.length;i++){
         bst.insert(nums[i])
     }
     bst.prevOrder(bst.root)

15.深度优先,广度优先

<div id='root'>
        <span>123
            <a href="#">
                a1
            </a>
            <div>div
                <a>a2</a>
            </div>
        </span>
        <span>456
            <p>p</p>
        </span>
</div>

 //深度优先遍历--递归
    function deepTraval(node,nodeList) {
        if (node) {
            nodeList.push(node);
            var children = node.children;
            for (var i = 0; i < children.length; i++)
                //每次递归的时候将  需要遍历的节点  和 节点所存储的数组传下去
                deepTraval(children[i],nodeList);
        }
        return nodeList;
    }
  //深度优先--非递归
    function deepTraval2(node){
        let nodes=[];
        if(node!=null){
            let stack=[];//同来存放将来要访问的节点
            stack.push(node);
            while(stack.length!=0){
                let item=stack.pop();//正在访问的节点
                nodes.push(item);
                let childrens=item.children;
                for(let i=childrens.length-1;i>=0;i--)//将现在访问点的节点的子节点存入stack,供将来访问
                    stack.push(childrens[i]);
            }
        }
        return nodes;
    }

    //广度优先——递归
    var widthTraval2=function(node){
        var nodes=[];
        var i=0;
        while(node!=null){
            nodes.push(node);
            widthTraval2(node.nextElementSibling);
            node=nodes[i++];
            widthTraval2(node.firstElementChild);
        }
        return nodes;
    };
    //广度优先遍历--非递归
    var widthTraval=function(node){
        let nodes=[];
        while(node!=null){
            var queue=[];
            queue.unshift(node);
            while(queue.length!=0){
                var item=queue.shift();
                nodes.push(item);
                var children=item.children;
                for(var i=0;i<children.length;i++){
                    queue.push(children[i])
                }
            }
            return nodes;
        }
    };
    var root = document.getElementById('root')
    console.log(deepTraval(root,nodeList=[]));
    console.log(deepTraval2(root))
    console.log(widthTraval(root))
    console.log(widthTraval2(root))

16.实现一个EventListener类,包含on,off,emit方法:

1、on(event,fn):监听event事件,事件触发时调用fn函数;

2、once(event,fn):为指定事件注册一个单次监听器,单次监听器最多只触发一次,触发后立即解除监听器;

3、emit(event,arg1,arg2,arg3...):触发event事件,并把参数arg1,arg2,arg3....传给事件处理函数;

4、off(event,fn):停止监听某个事件。

 
function Event() {
  this._events = {};
}
 
Event.prototype.on = function(type, fn) {
  if (!this._events[type]) {
    this._events[type] = []
  }
  this._events[type].push(fn);
}
 
Event.prototype.off = function(type, fn) {
  if (!this._events[type]) {
    return;
  }
  if (!fn) {
    this._events[type] = undefined;
    return;
  }
  var index = this._events[type].indexOf(fn);
  this._events[type].splice(index, 1);
}
 
Event.prototype.emit = function(type) {
  if (!this._events[type]) {
    return;
  }
  this._events[type].forEach(fn => fn());
}
 
Event.prototype.once = function(type, fn) {
  var _ = this;
  var _fn = () => {
    fn.apply(_, arguments);
    this.off(type);
  };
 
  this.on(type, _fn);
}
复制代码

17.合并两个有序链表

function Node(data){
        this.data=data;
        this.next=null;
    }
    function List(){
        this.head=null;//表头节点
        this.length=0;//链表长度
    }
    List.prototype.insert=function(val){
        var node=new Node(val);
        if(!this.head){
            this.head=node;
        }
        else{
            var current=this.head;
            while(current.next){
                current=current.next
            }
            current.next=node;
        }
        this.length++;
    };
    var arr1=[1,3,5,7,9];
    var arr2=[2,4,6,8,9];
    var list1=new List();
    var list2=new List();
    arr1.forEach((key)=>{
        list1.insert(key)
    });
    arr2.forEach((key)=>{
        list2.insert(key)
    })

    var merge=function(list1,list2){
        var list = new List();
        // 第一个链表的头节点
        var current1 = list1.head;
        // 第二个链表的头节点
        var current2 = list2.head;

        // 用循环把两个链表的key按顺序插入到新链表
        while (current1 && current2) {
            if (current1.data < current2.data) {
                list.insert(current1.data);
                current1 = current1.next;
            } else {
                list.insert(current2.data);
                current2 = current2.next;
            }
        }

        // 找到新链表的最后一个节点
        var current = list.head;
        while(current.next){
            current = current.next;
        }

        // 循环完成以后,把第二个链表剩余部分插入到新链表
        if (current2) {
            while (current2) {
                list.insert(current2.data);
                current2 = current2.next;
            }
        }
        // 循环完成以后,把第一个链表剩余部分插入到新链表
        if (current1) {
            while (current1) {
                list.insert(current1.data);
                current1 = current1.next;
            }
        }

        return list;
    }
    var merge2=function(list1,list2){
        // 存放两个链表key的数组
        var array = [];
        // 最终需要返回的新链表
        var list = new List();
        // 第一个链表的头节点
        var listHead1 = list1.head;
        // 第二个链表的头节点
        var listHead2 = list2.head;

        // 把第一个链表的所有key存进数组
        while (listHead1) {
            array.push(listHead1.data);
            listHead1 = listHead1.next;
        }
        // 把第二个链表的所有key存进数组
        while (listHead2) {
            array.push(listHead2.data);
            listHead2 = listHead2.next;
        }
        // 对数组排序
        array = array.sort(function(a, b){
            return a - b;
        })
        console.log(array)
        // 使用数组重新构建一个链表
        array.forEach(function(key){
            list.insert(key);
        });

        return list;
    }
    console.log(merge2(list1,list2))

18.找一篇英文文章中出现次数最多的前三个单词

 var counts = function(str){
        var array = str.match(/[a-z]+/gi);
        console.log(array);
        var obj = {};
        for(var i = 0; i < array.length; i++){
            var key = array[i];
            !obj[key] ? obj[key] = 1 : obj[key]++;
        }
        var arr=[];
        for(var k in obj){
            arr.push(obj[k]);
        }
        arr.sort();
        var length=arr.length
        console.log(arr[length-1])
        console.log(arr[length-2])
        console.log(arr[length-3])
        for(var k in obj){
            if(obj[k]===arr[length-1]){
                console.log(k+" "+obj[k]);
            }
           if(obj[k]===arr[length-2]){
                console.log(k+" "+obj[k]);
            }
            if(obj[k]===arr[length-3]){
                console.log(k+" "+obj[k]);
            }
        }
    }
    counts("Age has reached the end of the beginning of a word." +
        " May be be be guilty in his seems to passing a lot of different life " +
        "became the appearance of same day;");

19.判断A数组是否是B数组子集

var arr1=[11, 16, 18, 22, 33, 56, 66];
 var arr2=[11, 16, 18, 22, 33, 33, 44, 56, 66, 88, 99];
 function isInArray(arr1,arr2){
     if(arr1.length>arr2.length){
         return false;
     }
     var i=0,j=0;
     while(i<arr2.length && j<arr1.length){
         if(arr1[i]>arr2[j]){
             j++;
         }
         else if(arr1[i]===arr2[j]){
             i++;
             j++;
         }
         else{
             return false;
         }
     }
     if(i<arr1.length){
         return false;
     }else{
         return true;
     }

 }
 isInArray(arr1,arr2);

将数组转化为字符串方法:

var a = [2,3,4,5,6,7,8,9,10]
var b = [2,3]
a.find((item, index, arr)=>arr.slice(index, index + b.length).toString() === b.toString()) !== undefined

20.冒泡排序的优化方案

//做swap标记,若循环下来没有交换过则说明已经排序完成。复杂度 最优n 平均n2 最差n2
 function bubbleSort(arr) {
        let loopTimes = 0
        var temp;
        for (let i = 0, len = arr.length; i < len; i++) {
            let finished = true
            for (let j = 0, len = arr.length - i - 1; j < len; j++) {
                if (arr[j] > arr[j + 1]) {
                    finished = false;
                    temp = arr[j + 1]
                    arr[j + 1] = arr[j]
                    arr[j] = temp
                }
            }
            loopTimes++;
            if (finished)
                break
        }
        return loopTimes
    }

    let arr = [2, 3, 9, 4, 5]
    bubbleSort(arr)
    console.log('loopTimes:' + bubbleSort(arr))
    console.log('the Array after sorting:' + arr)

21.求中位数

function middle(){
        let args=[...arguments]; //收集参数转为数组
        var arr=args.sort((x,y)=>{
            return x-y;
        })//排序
       if(arr.length%2===0){
            return (arr[arr.length/2]+arr[arr.length/2-1])/2;
       }else{
            return arr[parseInt(arr.length/2)]
       }

    }
    var mid=middle(1,3,5,4,6,2,10,11,8,9,7)
​    console.log(mid)

22.给定一个字符串str,只会出现{}()[]这六种字符,看字符串中的括号是否是匹配的:

 function isMatch(str){
        let stack = [];
        for(let i=0;i<str.length;i++){
            if(str[i] === '(' || str[i] === '{' || str[i] === '['){
                stack.push(str[i])
            }else if(str[i] === ')' || str[i] === '}' || str[i] === ']'){
                let target = stack[stack.length-1];
                if(
                    target === '(' && str[i] === ')' ||
                    target === '{' && str[i] === '}' ||
                    target === '[' && str[i] === ']'
                ){
                    stack.pop();
                }else{
                    return false;
                }
            }
        }
        return !stack.length
    }
    console.log(isMatch("({} ([)[{}"));

23.给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后。时间复杂度为O(n),空间复杂度O(1)

function  strRGB(str2) {
        var i, sG = -1, sB = -1;
        var str=str2.split("")
        for (i = 0; i<str.length; i++) {
            if (str[i] === 'R') {
                if (sG !== -1) {
                    [str[sG],str[i]]=[str[i],str[sG]]
                    sG++;
                }
                if (sB !== -1) {
                    [str[sB],str[i]]=[str[i],str[sB]]
                    sB++;
                }
            }
            else if (str[i] === 'G') {
                if (sB !==-1) {
                    [str[sB],str[i]]=[str[i],str[sB]]
                    sB++;
                    if (sG === -1){
                        sG = sB - 1;
                    }
                }
                else if (sG === -1){
                    sG = i;
                }
            }
            else if (sB === -1){
                sB = i;
            }
        }
        return str.join("");
    }
    console.log(strRGB("RRRGBBGRRGG"));

22.实现一个set

/*add(value):向集合添加一个新的项。

delete(value):从集合移除一个值。

has(value):如果值在集合中,返回true,否则返回false。

clear():移除集合中的所有项。

size():返回集合所包含元素的数量。与数组的length属性类似。

values():返回一个包含集合中所有值的数组。

并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。

交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。

差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。

子集:验证一个给定集合是否是另一集合的子集。*/
class Set {
	constructor() {
		this.items = {};
	}

	has(value) {
		return this.items.hasOwnProperty(value);
	}

	add(value) {
		if (!this.has(value)) {
			this.items[value] = value;
			return true;
		} else {
			return false;
		}
	}

	remove(value) {
		if (this.has(value)) {
			delete this.items[value];
			return true;
		} else {
			return false;
		}
	}

	clear() {
		this.items = {};
	}

	size() {
		let count = 0;
		for (let key in this.items) {
			if (this.items.hasOwnProperty(key)) {
				++count;
			}
		}
		return count;
	}

	keys() {
		let keys = [];
		for (let key in this.items) {
			if (this.items.hasOwnProperty(key)) {
				keys.push(key);
			}
		}
		return keys;
	}

	values() {
		let values = [];
		for (let value in this.items) {
			if (this.items.hasOwnProperty(value)) {
				values.push(this.items[value]);
			}
		}
		return values;
	}

}
// 并集 A U B
Set.prototype.union = function (otherSet) {
	let unionSet = new Set();
	let values = this.values();
	for (let i = 0; i < values.length; i++) {
		unionSet.add(values[i]);
	}
	values = otherSet.values();
	for (let i = 0; i < values.length; i++) {
		unionSet.add(values[i]);
	}
	return unionSet;
}

// 交集 A ∩ B
Set.prototype.intersection = function (otherSet) {
	let intersectionSet = new Set();
	let values = this.values();

	for (let i = 0; i < values.length; i++) {
		if (otherSet.has(values[i])) {
			intersectionSet.add(values[i]);
		}
	}
	return intersectionSet;
}

// 差集 A-B
Set.prototype.difference = function (otherSet) {
	let differenceSet = new Set();
	let values = this.values();

	for (let i = 0; i < values.length; i++) {
		if (!otherSet.has(values[i])) {
			differenceSet.add(values[i]);
		}
	}
	return differenceSet;
}

// 子集 A⊆B
Set.prototype.subset = function (otherSet) {
	if (this.size() > otherSet.size()) {
		return false;
	} else {
		let values = this.values();
		for (let i = 0; i < values.length; i++) {
			if (!otherSet.has(values[i])) {
				return false;
			}
		}
		return true;
	}
}

let set = new Set();
set.add(1);
set.add(2);
// set.add(5);
// set.add(9);
console.log(set); // Set { items: { '1': 1, '2': 2 } }
console.log(set.keys()); // [ '1', '2' ]
console.log(set.values()); // [ 1, 2 ]
console.log(set.size()); // 2
set.remove(1);
console.log(set); // Set { items: { '2': 2 } }
let otherset = new Set();
otherset.add(1);
otherset.add(2);
otherset.add(3);
otherset.add(4);
console.log(set.union(otherset)); // Set { items: { '1': 1, '2': 2, '3': 3, '4': 4 } }
console.log(set.intersection(otherset)); //Set { items: { '2': 2 } }
console.log(set.difference(otherset)); // Set { items: {} }
console.log(set.subset(otherset)); // true

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值