其他分享
首页 > 其他分享> > 前端面试汇总大全—剑指offer刷题—js牛客网刷题

前端面试汇总大全—剑指offer刷题—js牛客网刷题

作者:互联网

1, 二维数组中的查找

function Find(target, array) {
  const n = array.length,
    m = array[0].length;
  let row = n - 1,
      col = 0;
  if (m === 0 && n === 0) {
    return false;
  }
  while (row >= 0 && col <= m - 1) {
    if (array[row][col] > target) {
      row--;
    } else if (array[row][col] < target) {
      col++;
    } else return true;
  }
  return false;
}

2, 替换空格

function replaceSpace(str) {
  return str.replace(/\s/g, '%20');   // \s 匹配任意的空白符 
}

3, 从头到尾打印链表

/* function ListNode(x){
 this.val = x;
 this.next = null;
 }*/
function printListFromTailToHead(head) {
  // write code here
  const res = [];
  let pNode = head;
  while (pNode !== null) {
    res.unshift(pNode.val);
    pNode = pNode.next;
  }
  return res;
}

4, 重建二叉树

/* function TreeNode(x) {
 this.val = x;
 this.left = null;
 this.right = null;
 } */
function reConstructBinaryTree(pre, vin) {
  if (pre.length === 0 || vin.length === 0) {   return null;  }
  // 前序第一个是根节点,也是中序左右子树的分割点
  const index = vin.indexOf(pre[0]),
    left = vin.slice(0, index),
    right = vin.slice(index + 1);
  return {
    val: pre[0],   // 递归左右子树的前序、中序
    left: reConstructBinaryTree(pre.slice(1, index + 1), left),
    right: reConstructBinaryTree(pre.slice(index + 1), right)
  };
}

5, 用两个栈实现队列

const outStack = [],
  inStack = [];
function push(node) {
  // write code here
  inStack.push(node);
}
function pop() {
  // write code here
  if (!outStack.length) {
    while (inStack.length) {
      outStack.push(inStack.pop());
    }
  }
  return outStack.pop();
}

6, 旋转数组中的最小数字

// 第一种
function minNumberInRotateArray1(rotateArray) {
  // write code here
  if (rotateArray.length === 0) return 0;
  for (let i = 0; i < rotateArray.length; i++) {
    if (rotateArray[i] > rotateArray[i + 1]) return rotateArray[i + 1];
  }
  return rotateArray[0];
}
// 第二种
function minNumberInRotateArray2(rotateArray) {
  let left = 0,
    right = rotateArray.length - 1;
  while (right - left > 1) {
    let mid = left + (right - left) >> 1;
    mid = left + (right - left >> 1);
    if (rotateArray[mid] > rotateArray[right]) {
      left = mid;
    } else {
      right = mid;
    }
  }
  return Math.min(rotateArray[left], rotateArray[right]);
}

7, 斐波那契数列

function Fibonacci(n) {
  let f = 0,
    g = 1;
  while (n--) {
    g += f;
    f = g - f;
  }
  return f;
}

8, 跳台阶

function jumpFloor(number) {
  let f = 1,
    g = 2;
  while (--number) {
    g += f;
    f = g - f;
  }
  return f;
}

9, 变态跳台阶

function jumpFloorII(number) {
  let i = 1;
  while (--number) {
    i *= 2;
  }
  return i;
}

10, 矩形覆盖

function rectCover(number) {
  if (number === 0) return 0;
  let f = 1,
    g = 2;
  while (--number) {
    g += f;
    f = g - f;
  }
  return f;
}

11, 二进制中1的个数

// 第一种
function NumberOf1(n) {
  let count = 0,
    flag = 1;
  while (flag) {
    // 循环的次数等于整数二进制的位数,32位的整数需要循环32位
    if (flag & n) count++;
    flag = flag << 1;
  }
  return count;
}
// 第二种
function newNumberOf1(n) {
  let count = 0;
  while (n) {
    n = n & n - 1; // 核心
    count++;
  }
  return count;
}

12, 数值的整数次方

function Power(base, exponent) {
  let res = 1,
    n;
  if (exponent > 0) {    // 指数大于0的情况下  
    n = exponent;
  } else if (exponent < 0) {    // 指数小于0的情况下   
    if (!base) throw new Error('分母不能为0');
    n = -exponent;
  } else {       // 指数等于0的情况下  
    return 1;
  }
  while (n) {    // 也可以用递归做,这里采用了循环  
    if (n & 1)  // 当指数为奇数时,包括了1      
      res *= base;
    base *= base;
    n >>= 1;
  }
  return exponent > 0 ? res : 1 / res;
}

13, 调整数组顺序使奇数位于偶数前面

function reOrderArray(array) {
  // oddBegin主要是用作奇数的索引,oddCount是用作偶数的索引,newArray用来存储,以空间换时间,复杂度为O(n)
  let oddBegin = 0,
    oddCount = 0;
  const newArray = [];
  for (let i = 0; i < array.length; i++) {
    if (array[i] & 1) {
      oddCount++;
    }
  }
  for (let i = 0; i < array.length; i++) {
    if (array[i] & 1) {
      newArray[oddBegin++] = array[i];
    } else {
      newArray[oddCount++] = array[i];
    }
  }
  return newArray;
}

14, 链表中倒数第K个结点

/* function ListNode(x){
 this.val = x;
 this.next = null;
 }*/
function FindKthToTail(head, k) {
  if (head === null || k <= 0) return null;
  let pNode1 = head,
    pNode2 = head;
  while (--k) {
    if (pNode2.next !== null) {
      pNode2 = pNode2.next;
    } else {
      return null;
    }
  }
  while (pNode2.next !== null) {
    pNode1 = pNode1.next;
    pNode2 = pNode2.next;
  }
  return pNode1;
}

15, 反转链表

/* function ListNode(x){
 this.val = x;
 this.next = null;
 }*/
function ReverseList(pHead) {
  // write code here
  let pPre = null,
    pNext = null;
  while (pHead !== null) {
    pNext = pHead.next;
    pHead.next = pPre;
    pPre = pHead;
    pHead = pNext;
  }
  return pPre;
}

16, 合并两个排序的链表

/* function ListNode(x){
 this.val = x;
 this.next = null;
 }*/
function Merge(pHead1, pHead2) {
  let pMergeHead = null;
  // write code here
  if (pHead1 === null) return pHead2;
  if (pHead2 === null) return pHead1;
  if (pHead1.val < pHead2.val) {
    pMergeHead = pHead1;
    pMergeHead.next = Merge(pHead1.next, pHead2);
  } else {
    pMergeHead = pHead2;
    pMergeHead.next = Merge(pHead1, pHead2.next);
  }
  return pMergeHead;
}

30, 连续子数组和的最大值

function FindGreatestSumOfSubArray(array) {
  if (array.length <= 0) return 0;
  let sum = array[0],
    max = array[0];
  for (let i = 1; i < array.length; i++) {
    if (sum < 0) sum = array[i];
    else sum = sum + array[i];
    if (sum > max) max = sum;
  }
  return max;
}

31, 1~n整数中1出现的次数

是按位取反的意思,~就是再转回来,两个按位取反,类型的转换成数字符号。

// 暴力解法
function NumberOf1Between1AndNSolution(n) {
  let ones = 0;
  for (let i = 0; i <= n; i++) {
    let num = i;
    while (num) {
      if (num % 10 === 1) {
        ones++;
      }
      num = ~~(num / 10);
    }
  }
  return ones;
}
// 优化版
function NumberOf1Between1AndNSolution2(n) {
  if (n <= 0) return 0;
  let count = 0;
  for (let i = 1; i <= n; i *= 10) {
    const a = ~~(n / i),
      b = n % i;
    count = count + ~~((a + 8) / 10) * i + (a % 10 === 1) * (b + 1);
  }
  return count;
}

34, 第一个只出现一次的字符

function FirstNotRepeatingChar(str) {
  if (str.length < 1 || str.length > 10000) return -1;
  const map = {};
  for (let i = 0; i < str.length; i++) {
    if (!map[str[i]]) {
      map[str[i]] = 1;
    } else {
      map[str[i]]++;
    }
  }
  for (let i = 0; i < str.length; i++) {
    if (map[str[i]] === 1) {
      return i;
    }
  }
  return -1;
}

40, 数组中只出现一次的数字

// 第一种: indexOf是从前向后查 而lastIndexOf是从后向前查 但是二者返回索引都为下标
function FindNumsAppearOnce(array) {
 const res = [];
 for (let i = 0; i < array.length; i++) {
   if (array.indexOf(array[i]) === array.lastIndexOf(array[i])) {
     res.push(array[i]);
   }
 }
 return res;
}
// 第二种
function FindNumsAppearOnce2(array) {
 const map = {},
   res = [];
 for (let i = 0; i < array.length; i++) {
   if (!map[array[i]]) {
     map[array[i]] = 1;
   } else {
     map[array[i]]++;
   }
 }
 for (let i = 0; i < array.length; i++) {
   if (map[array[i]] === 1) {
     res.push(array[i]);
   }
 }
 return res;
}
// 第三种
function FindNumsAppearOnce3(array) {
 let tmp = array[0];
 for (let i = 1; i < array.length; i++) {
   tmp = tmp ^ array[i];
 }
 if (tmp === 0) return;
 let index = 0; // 记录第几位是1
 while ((tmp & 1) === 0) {
   tmp = tmp >> 1;
   index++;
 }
 let num1 = 0,
   num2 = 0;
 for (let i = 0; i < array.length; i++) {
   if (isOneAtIndex(array[i], index)) num1 = num1 ^ array[i];
   else num2 = num2 ^ array[i];
 }
 return [num1, num2];
}
function isOneAtIndex(num, index) {
 num = num >> index;
 return num & 1;
}

41, 和为S的字符串

假设序列的开始数字为a,结束数字为a+i,那么有(a+i-a+1)(a+a+i)/2=sum
也就是(i+1)(2a+i)=2
sum,只需要找出这样的a和i就行,再根据a和i得出序列。

function FindContinuousSequence(sum) {
  let a = 0,
    half = sum >> 1;
  const res = [];
  while (half--) {
    a++;
    let i = 1;
    while ((i + 1) * (2 * a + i) < 2 * sum) { i++; }
    if ((i + 1) * (2 * a + i) === 2 * sum) {
      const tmp = [];
      tmp.push(a);
      tmp.push(i);
      res.push(tmp);
    }
  }
  for (let i = 0; i < res.length; i++) {
    let num = res[i][1],
      k = 1;
    const tmp = [];
    tmp.push(res[i][0]);
    while (num--) {
      tmp.push(res[i][0] + k);
      k++;
    }
    res[i] = tmp;
  }
  return res;
}

42, 和为S的字符串

function FindNumbersWithSum(array, sum) {
  if (array.length < 2) return [];
  let left = 0,
    right = array.length - 1;
  const res = [];
  while (left < right) {
    if (array[left] + array[right] < sum) {
      left++;
    } else if (array[left] + array[right] > sum) {
      right--;
    } else {
      res.push(array[left], array[right]);
      break;
    }
  }
  return res;
}

44, 单词翻转序列

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

47, 求1+2+3+...+n

// 用右移运算符,再结合等差数列求和公式。
function Sum_Solution(n)
{
    var res = Math.pow(n, 2) + n;
    return res >> 1;
}
//第二种   逻辑运算的短路特性
function SumSolution(n) {
  return n && Sum_Solution(n - 1) + n;
}

48, 不用加减乘除做加法

function Add(num1, num2) {
  while (num2 !== 0) {
    const tmp1 = num1 ^ num2;
    num2 = (num1 & num2) << 1;
    num1 = tmp1;
  }
  return num1;
}

49, 把字符串转换成整数

function StrToInt(str) {
  let res = 0,
    flag = 1;
  const n = str.length;
  if (!n) return 0;
  if (str[0] === '-') {
    flag = -1;
  }
  for (let i = str[0] === '+' || str[0] === '-' ? 1 : 0; i < n; i++) {
    if (!(str[i] >= '0' && str[i] <= '9')) return 0;
    res = (res << 1) + (res << 3) + (str[i] - '0');
  }
  return res * flag;
}

55,链表中环的入口节点

/* function ListNode(x){
 this.val = x;
 this.next = null;
 }*/
function EntryNodeOfLoop(pHead) {
  let fast = pHead;
  let slow = pHead;
  while (fast !== null && fast.next !== null) {
    slow = slow.next;
    fast = fast.next.next;
    if (fast === slow) {  // 两者相遇     
      let p = pHead;
      while (p !== slow) {
        p = p.next;
        slow = slow.next;
      }
      return p;
    }
  }
  return null;
}
Cookie_fzx 发布了82 篇原创文章 · 获赞 22 · 访问量 4万+ 私信 关注

标签:function,return,offer,res,js,length,let,网刷题,array
来源: https://blog.csdn.net/image_fzx/article/details/103951258