算法

随着互联网发展速度放缓,企业招聘时更挑人,所以越来越多的公司,喜欢在面试中考察算法,特别是在二面的时候,所以算法一定得有所准备。

实现bind

function deepClone(obj){
  if (obj === null | typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new Date(RegExp);
  const newObj = new obj.constuctor;
  for (let key in obj) {
    if(obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key]);
    }
  }

  return newObj;
}

实现深拷贝

function deepClone(obj){
  if (obj === null | typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new Date(RegExp);
  const newObj = new obj.constuctor;
  for (let key in obj) {
    if(obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key]);
    }
  }

  return newObj;
}

不需要借助第三个临时变量,实现两个变量的交换

function swap(a,b){
  b = b - a;
  a = a + b;
  b = a - b;
  return [a,b];
}

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

function titleCase(str) {
  var lstr = str.toLowerCase().split(' ');
  for(var i = 0 ; i < lstr.length; i++) {
    lstr[i] = lstr[i][0].toUpperCase() + lstr[i].substring(1, lstr[i].length);
  }
  var res = lstr.join(' ');
  return res;
}
titleCase("good night"); // Good Night

清除字符串前后的空格(兼容所有浏览器)

function trim(str) {
  if (str & typeof str === "string") {
    return str.replace(/(^s*)|(s*)$/g, ''); //去除前后空白符
  }
}

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

let unique =  function(arr){
  let hash={};
  let data=[];
  for (let i=0;i < arr.length; i++){
    if (!hash[arr[i]])  {
      hash[arr[i]] = true;
      data.push(arr[i]);
    }      
  }
  return data
}

翻转字符串

  • split()字符串转成数组;
  • reverse()翻转数组;
  • join()数组转化成字符串。
function reverseString(str){    
  return str.split('').reverse().join('');	
}

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

  • 转化成数组;
  • 根据元素长度排序;
  • 输出最长元素并返回长度。
function findLongestString(str){
  var arr = str.split(' ');	
  var arrSort = arr.sort(function (a,b) {	   
    return b.length - a.length;
  });
  return [arrSort[0], arrSort[0].length];
}

截断一个字符串,如果字符串的长度比指定的参数num长,则把多余的部分用...来表示

function truncate(str, num){
  var trStr = str.slice(0, num);
  if (trStr.length > num) {					
    return trStr.concat('...');
  } else {
    return str;
  }
}

判断一个字符串中出现次数最多的字符,统计这个次数

funcion findMaxStrCount(str) {
  var countObj = {};
  var max = '';
  for(var i = 0; i < str.length; i++) {
    var cur = str[i];
    if(!countObj[cur]) {
      countObj[cur] = 0;
    } 
    countObj[cur]++;
    if(max === '' || countObj[cur] > countObj[max]) { max = cur; }
  }
  return [max, countObj[max]];
}

快速排序(Quick Sort)

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

var quickSort = function(arr) {
 if (arr.length <= 1) { return arr; }
 var pivotIndex = Math.floor(arr.length / 2);
 var pivot = arr.splice(pivotIndex, 1)[0];
 var left = [];
 var right = [];
 for (var i = 0; i < arr.length; i++){
  if (arr[i] < pivot) {
   left.push(arr[i]);
  } else {
   right.push(arr[i]);
  }
 }
 return quickSort(left).concat([pivot], quickSort(right));
};

用递归实现斐波那契数列

function fib(n){
  if(typeof n === 'number' && n > 0 && parseInt(n) === n ) {
    return n < 3 ? 1 : fib(n-1)+fib(n-2); 
  } else {
    return '输入不合法,请输入正整数!';
  }   
}

数组中两两之差的最大值?

function maxDiffInArray(arr){
  if ( arr instanceof Array) {
    if (arr.length) {
      let max = arr[0], min = arr[0];
      for (let i = 0; i < arr.length; i++) {
        if ( typeof arr[i]  !== 'number' ) {
          return '输入不合法,数组存在非数字类型元素,请输入数字数组';
        }
        max = Math.max(arr[i], max), min = Math.min(arr[i], min);
      }   
      return max - min; 
    } else {
      return '输入不合法,数组为空,请输入非空数组';
    }
  } else {
    return '输入不合法,请输入非空数组';
  } 
}

单向链表反转-JS实现

function reverseLinkedList(head) {
     if (head === null || head.next === null) {
         return head;
     }
     let newHead = null; 
     let nextHead = null;
     while (head) {
        nextHead = head.next; // 先记住当前节点的下一节点
        head.next = newHead; // 把当前节点的指针指向上一节点
        newHead = head; // 保留上一节点
        head = nextHead; // 遍历下一节点
     }
     return newHead; // 最后head 为null跳出遍历,此时newHead就成了新链表的头结点了
}

变形的链表反转

给定一个单链表的头节点 head,实现一个调整单链表的函数,使得每K个节点之间为一组进行逆序,并且从链表的尾部开始组起,头部剩余节点数量不够一组的不需要逆序。

例如:链表:1->2->3->4->5->6->7->8->null, K = 3。那么 6->7->8,3->4->5,1->2各位一组。调整后:1->2->5->4->3->8->7->6->null。其中 1,2不调整,因为不够一组。

    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode temp = head;
        for (int i = 1; i < k && temp != null; i++) {
            temp = temp.next;
        }
        //判断节点的数量是否能够凑成一组
        if(temp == null)
            return head;

        ListNode t2 = temp.next;
        temp.next = null;
        //把当前的组进行逆序
        ListNode newHead = reverseList(head);
        //把之后的节点进行分组逆序
        ListNode newTemp = reverseKGroup(t2, k);
        // 把两部分连接起来
        head.next = newTemp;
        
        return newHead;
    }
    
    //逆序单链表
    private static ListNode reverseList(ListNode head) {
        if(head == null || head.next == null)
            return head;
        ListNode result = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return result;
    }

public ListNode solve(ListNode head, int k) {
    // 调用逆序函数
    head = reverse(head);
    // 调用每 k 个为一组的逆序函数(从头部开始组起)
    head = reverseKGroup(head, k);
    // 在逆序一次
    head = reverse(head);
    return head;
}

小结

这里所列举的一些算法题,应付多数互联网公司应该就可以了,不过若想去字节跳动这个算法驱动的公司,最后还是的去Leecode等刷题网站刷一百题以上的算法。