刷题总结一

       最近很多公司陆陆续续开始了提前批校招,虽然大部分还没开始,所以可以开始积累总结了,现在总结的都是针对剑指offer 里的编程题,很典型也很经典,不定期更新吧

一、数组

        数组如果在 js 中用的好的话,笔试中用到的会占大部分。

       1)数组调用函数

           “包含 Min 函数的栈”:求一维数组中的最小值/ 最大值:Math.min.apply(this/null,目标数组)  Math.max.apply(this/null,目标数组)  

                var arr = [1,3,6,8,2,10]; var minNum = Math.min.apply(null,arr);

                var maxNum = Math.max.apply(null,arr);

               console.log(minNum,maxNum);

                运行结果是:1 , 10 ;  Math.min 可以实现得到数组中最小的一项,Math.max 可以实现得到数组中最小的一项

         2) 数组常用方法:reduce、map、filter 、concat、foreach、some、unshift(前插)、shift、isArray、join、splice、slice 

              "变态跳台阶":跳上 n 级台阶可以用 1到n 种单次跳法,求跳上 n 级台阶共有多少种跳法。找规律可以发现,最后一个数的值,是之前值的和。或者认为拆分后,是之前子项的考虑的全部情况。所以这里用 reduce 函数是最方便的。

// write code here
var result = [1,1];
for(var i=2;i<=number;i++){
    var temp = result.reduce(function(acc,val){
       return acc+val;
    })
    result[i] = temp;
}
return result[number];

           “调整数组里的奇数位于偶数之前”:遍历一次原数组,对于奇数放入数组1,偶数放入数组2。再用concat 连接两数组,返回最后的数组。

         3)数组规律的判断:

           “顺时针打印矩阵”:给出一个 n*n 的矩阵,顺时针输出其中的数。主要是找到下标变化的规律:

function printMatrix(matrix)
{
    // write code here
    var row=matrix.length;
    var col=matrix[0].length;
    var res=[];
    if(row==0||col==0){
        return res;
    }
    var left=0,
        top=0,
        right=col-1,
        bottom=row-1;
    while(left<=right&&top<=bottom){
        for(var i=left;i<=right;i++)
            res.push(matrix[top][i]);
        for(var i=top+1;i<=bottom;i++)
            res.push(matrix[i][right]);
        if(top!=bottom)
            for(var i=right-1;i>=left;i--)
                res.push(matrix[bottom][i]);
        if(left!=right)
            for(var i=bottom-1;i>top;i--)
                res.push(matrix[i][left]);
        left++,top++,right--,bottom--;
    }
    return res;
}

         

二、链表

      链表通常与栈、队列、二叉树这些基本数据结构概念联系在一起。     

      1)栈实现队列:

              “用两个栈实现队列”:初始化两个数组,第一个存储完所有的数据,再判断第二个数组是否为空,若第二个数组为空且第一个数组不为空,则遍历第一个数组中的元素全部存入第二个数组;若第二个数组不空,则弹出。

      2)“重建二叉树":

            给出一个二叉树的前序遍历和中序遍历,输出完整的二叉树结构。前序遍历的第一个元素是根节点,中序遍历的根节点左边是左子树内容,右边是右子树内容。根据划定的子树范围,用中值下标不断进行细分。

function reConstructBinaryTree(pre, vin)
{
    var len = pre.length;
    return createTree(pre, vin, 0, len - 1, 0);
}
function createTree(pre, vin, left, right, rootIndex){
    var val = pre[rootIndex];
    var midIndex = vin.indexOf(val);
    var root = new TreeNode(val);
    if(midIndex > left) root.left = createTree(pre, vin, left, midIndex - 1, rootIndex + 1 );
    if(midIndex < right) root.right = createTree(pre, vin, midIndex + 1, right, rootIndex + midIndex -left + 1 );
    return root;
}

          3) “从头到尾打印链表”

                 链表部分只给出了头部,那就新建一个数组,将链表的内容依次存入数组,最后输出链表的翻转,用 reverse() 实现。

         4)“输出链表倒数第K个节点”

              将链表中的数依次存入数组,输出数组的第 length-k 个数

         5)“反转链表”

              输入链表,反转链表后,输出新的表头。链表的值依次存入数组,再从数组中弹出存入链表。利用数组的栈性质。

三、递归

     很多情况下,笔试题也会涉及到递归调用

     1)涉及到1到n 的数字总结类型

            比如剑指offer 中的 “跳台阶问题”、“斐波那契数列”、“矩形覆盖”

           “矩形覆盖”:总结规律发现第三项开始,每项都是前两项的和。与斐波那契数列的操作一样

      2)链表

           “合并排序的链表”:输入两个单调递增的链表,输出一个合并后的单调递增链表

function Merge(pHead1, pHead2){
    // write code here
    let list = {}
    if(pHead1 === null){
        return pHead2;
    } else if (pHead2 === null) {
        return pHead1;
    }
    if(pHead1 > pHead2){
        list = pHead2;
        list.next = Merge(pHead2.next, pHead1);
    } else {
        list = pHead1;
        list.next = Merge(pHead2, pHead1.next)
    }
    return list;
}

          这里就是递归的链表表现形式,同时也可以看出,链表的表现形式就是对象的集合。

         “树的子结构”:判断B是不是A 的子结构

function HasSubtree(pRoot1, pRoot2){
  // write code here
  if (!pRoot1 || !pRoot2) {
    return false;
  }
  return isSubtree(pRoot1, pRoot2) || HasSubtree(pRoot1.left, pRoot2) || 
      HasSubtree(pRoot1.right, pRoot2);
}
function isSubtree(root1, root2) {
  if (!root2) {
    return true;
  }
  if (!root1) {
    return false;
  }
  if (root1.val == root2.val) {
    return isSubtree(root1.left, root2.left) &&
      isSubtree(root1.right, root2.right);
  } else {
    return false;
  }
}

       “二叉树的镜像”:将一个二叉树转化为镜像输出。一开始想的是把节点的左右子节点是否为空作为初始的判断,但是一直报错,所以用 root 判断即可

function(root){ 
   if(root === null) {
        return;
    }
    var temp = root.left;
    root.left = root.right;
    root.right = temp;
    Mirror(root.left);
    Mirror(root.right);
}

 

四、自定义函数

       这边的应用也有很多,都是为了在算法内部的自定义调用

       1)排序函数:有时自带的排序函数 sort 并不能达到想要的效果,就可以在排序函数内部自定义是递增或递减函数。比如“旋转最小数字”

五、基础知识

       1)正则表达式:

            正则表达式,用的好就能很方便完成一些操作。那就顺便复习一下正则表达式:

            通用形式:/\s 或 \S 或 \d 或 \D 等...../g

            匹配数量:* :任意数量,+:大于等于1 ,{n} : n 个,{n , } : 至少匹配n 次,{n , m }:匹配n 到 m 次

            匹配对象:x|y : 匹配 x 或y,[xyz] : 匹配其中的任意一个字符(“adxasd”,匹配的就是其中的 x),[^xyz] : 匹配非其中的任意一个字符(“adxasd”,匹配的就是其中的 adasd),[a-z]:字母范围,[^a-z]:匹配非字母范围中的字符,\d: 数字,\D: 非数字,\s :匹配空格制表符换页符等,\S 前者取非。

            “替换空格”:替换字符串中的空格为其他任意字符串:str.replace( /\s/g , "任意字符串" );

        2)二进制操作

           二进制之前没有非常注意,这里单独有一道题就是考察二进制的。

           “二进制中1的个数”:给出一个数,将数转换为二进制后,判断其中1的个数。这里考察的是基本运算符的本质问题,基本运算符中分逻辑运算符:或(||) 与(&&)非(!),和位运算符或(|) 与(&)非(~)异或(^)左移(<<)右移(>>)零填充右移(>>>)

function(n){
   var count = 0,flag=1;
   while(flag){
      if(n&flag)count++;
      flag=flag<<1;
   }
   return count;
}

          这里的小知识点就是,flag 每次右移1位,就相当于每次拿到的数是2的次幂值:2、4、8...,当输入的数与flag 做位与运算时,若在该次幂的位置上有1,则为true,否则为false。以此来统计目标数值中含有多少个1

        3)“数值的整数次方”

            这里就是对所有情况的数值的整数次做出对应的判断,求 base 的 exponent 次方。这里考虑 exponent 为 正、负、0是那种基本情况,其中在exponent 为负时,base 取到数次幂,同时判断不能为负值;在exponent 为正时,考虑base  的奇偶性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值