笔试编程题常用框架

目录

数组

前缀和、差分数组

双指针(快慢指针)

单调栈、单调队列:(单调递增/减)下/上一个更大/小元素

二叉树

数组和树

扁平结构(一维数组)转树

obj[item.id] = { ...item, children: [] }

pid === 0

!obj[pid]

obj[pid].children.push(treeitem)

数组扁平化

toString/join(',').split(',').map(Number) 

排序

快速排序

BFS:最短路径

回溯O(N!):选择/DFS

运算:栈

动态规划(Dynamic Programming,DP) 最值选择+重叠子问题

输入(i,j,w):for(i,j){w}

数组

 折半 / 二分查找

螺旋矩阵*

螺旋输出*(mxn矩阵,顺时针输出为一维数组)

旋转矩阵

行<->列,对角线

贪心

Jump Game II

到达last element的最小跳跃次数,nums[i]最远可以跳跃的步数

考前复习


数组

前缀和、差分数组

双指针(快慢指针)

单调栈、单调队列:(单调递增/减)下/上一个更大/小元素

二叉树

数组和树

扁平结构(一维数组)转树

obj[item.id] = { ...item, children: [] }

pid === 0

!obj[pid]

obj[pid].children.push(treeitem)

   //pid:parent id 
   let arr = [
        { id: 1, name: '部门1', pid: 0 },
        { id: 2, name: '部门2', pid: 1 },
        { id: 3, name: '部门3', pid: 1 },
        { id: 4, name: '部门4', pid: 3 },
        { id: 5, name: '部门5', pid: 4 },
    ]

    // // 上面的数据转换为 下面的 tree 数据
    // [
    //     {
    //         "id": 1,
    //         "name": "部门1",
    //         "pid": 0,
    //         "children": [
    //             {
    //                 "id": 2,
    //                 "name": "部门2",
    //                 "pid": 1,
    //                 "children": []
    //             },
    //             {
    //                 "id": 3,
    //                 "name": "部门3",
    //                 "pid": 1,
    //                 "children": [
    //                     {
    //                         id: 4,
    //                         name: '部门4',
    //                         pid: 3,
    //                         "children": [
    //                             {
    //                                 id: 5,
    //                                 name: '部门5',
    //                                 pid: 4,
    //                                 "children": []
    //                             },
    //                         ]
    //                     },
    //                 ]
    //             }
    //         ]
    //     }
    // ]


    function tree(items) {
        // 1、声明一个数组和一个对象 用来存储数据
        let arr = []
        let obj = {}
        // 2、给每条item添加children ,并连带一起放在obj对象里
        for (let item of items) {
            obj[item.id] = { ...item, children: [] }
        }
        // 3、for of 逻辑处理
        for (let item of items) {
            // 4、把数据里面的id 取出来赋值 方便下一步的操作
            let id = item.id
            let pid = item.pid
            // 5、根据 id  将 obj 里面的每一项数据取出来
            let treeitem = obj[id]
            // 6、如果是第一项的话 吧treeitem 放到 arr 数组当中
            if (pid === 0) {
                // 把数据放到 arr 数组里面
                arr.push(treeitem)
            } else {
                // 如果没有 pid 找不到 就开一个 obj { }
                if (!obj[pid]) {
                    obj = {
                        children: []
                    }
                }

                // 否则给它的 obj 根基 pid(自己定义的下标) 进行查找 它里面的children属性 然后push
                obj[pid].children.push(treeitem)
            }
        }
        // 返回处理好的数据
        return arr
    }
    console.log(tree(arr))

数组扁平化

toString/join(',').split(',').map(Number) 

要求将数组参数中的多维数组扩展为一维数组并返回该数组。
数组参数中仅包含数组类型和数字类型

function flatten(arr){
    // toString() + split() 实现   
    return arr.toString().split(',').map(item => Number(item));

    //join() + split() 实现
    return arr.join(',').split(',').map(item => Number(item));

    //reduce 实现
    return arr.reduce((target, item) => {
        return target.concat(Array.isArray(item) ? flatten(item) : item);
    }, [])

    // 递归实现
    let res = [];
    arr.forEach(item => {
        if (Array.isArray(item)) {
            res = res.concat(flatten(item))
      } else {
             res.push(item);
         }
     });
     return res;

    // 扩展运算符实现
       while(arr.some(item => Array.isArray(item))){
         arr = [].concat(...arr);
     }
     return arr;

    // flat()实现(这里不支持使用)
    return arr.flat(Infinity);
}

排序

快速排序

快速排序的基本思想是通过分治来使一部分均比另一部分小(大)再使两部分重复该步骤而实现有序的排列。核心步骤有:

  1. 选择一个基准值(pivot)
  2. 以基准值将数组分割为两部分
  3. 递归分割之后的数组直到数组为空或只有一个元素为止

key:

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

BFS:最短路径

BFS 找到的路径一定是最短的,但代价就是空间复杂度可能比 DFS 大很多

回溯O(N!):选择/DFS

运算:栈

动态规划(Dynamic Programming,DP) 最值选择+重叠子问题

输入(i,j,w):for(i,j){w}

数组

 折半 / 二分查找

判定树:描述 折半查找过程

ASLsucc≈log2(n+1)-1

keys: [L,R] while(L<=R)

螺旋矩阵*

/**
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function(n) {
    let startX = startY = 0;   // 起始位置
    let loop = Math.floor(n/2);   // 旋转圈数
    let mid = Math.floor(n/2);    // 中间位置
    let offset = 1;    // 控制每一层填充元素个数
    let count = 1;     // 更新填充数字
    let res = new Array(n).fill(0).map(() => new Array(n).fill(0));

    while (loop--) {
        let row = startX, col = startY;
        // 上行从左到右(左闭右开)
        for (; col < startY + n - offset; col++) {
            res[row][col] = count++;
        }
        // 右列从上到下(左闭右开)
        for (; row < startX + n - offset; row++) {
            res[row][col] = count++;
        }
        // 下行从右到左(左闭右开)
        for (; col > startY; col--) {
            res[row][col] = count++;
        }
        // 左列做下到上(左闭右开)
        for (; row > startX; row--) {
            res[row][col] = count++;
        }

        // 更新起始位置
        startX++;
        startY++;

        // 更新offset
        offset += 2;
    }
    // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    if (n % 2 === 1) {
        res[mid][mid] = count;
    }
    return res;
};

螺旋输出*(mxn矩阵,顺时针输出为一维数组)

function spiralPrint(matrix) {
    const m = matrix.length;
    const n = matrix[0].length;
    let startX = startY = 0;
    let loop = Math.min(Math.floor(m / 2), Math.floor(n / 2));
    
    while (loop--) {
        let row = startX, col = startY;

        for (; col < startY + n - 1; col++) {
            console.log(matrix[row][col]);
        }
        for (; row < startX + m - 1; row++) {
            console.log(matrix[row][col]);
        }
        for (; col > startY; col--) {
            console.log(matrix[row][col]);
        }
        for (; row > startX; row--) {
            console.log(matrix[row][col]);
        }

        startX++;
        startY++;

        m -= 2;
        n -= 2;
    }

    if (m === 1) {
        for (let i = startY; i < startY + n; i++) {
            console.log(matrix[startX][i]);
        }
    } else if (n === 1) {
        for (let i = startX; i < startX + m; i++) {
            console.log(matrix[i][startY]);
        }
    }
}

const matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
];

spiralPrint(matrix);

旋转矩阵​​​​​​​

行<->列,对角线

贪心

Jump Game II

到达last element的最小跳跃次数,nums[i]最远可以跳跃的步数

  1. 定义两个变量 maxReachsteps 分别表示当前能到达的最远位置和已经跳跃的步数。
  2. 遍历数组,对于每个位置 i,更新 maxReach 为当前位置能到达的最远距离。
  3. 当遍历到 i 超过了 maxReach 时,意味着需要再跳一步,并且更新 maxReach 为当前位置的最远距离。
  4. 每次更新 maxReach 时,步数 steps 也会增加一次。
  5. 当遍历完成时,steps 就是到达数组最后一个元素的最小跳跃次数。
function jump(nums) {
  let maxReach = 0; // 当前能到达的最远位置
  let steps = 0; // 已经跳跃的步数
  let end = 0; // 当前步数内可到达的最远位置
  
  for (let i = 0; i < nums.length - 1; i++) {
    maxReach = Math.max(maxReach, i + nums[i]); // 更新最远位置
    if (i === end) {
      end = maxReach; // 更新当前步数内的最远位置
      steps++; // 跳跃一步
    }
  }
  
  return steps;
}

const nums = [2, 3, 1, 1, 4];
console.log(jump(nums)); // 输出 2

考前复习

应该尽可能多的看各种各样的题目,思考五分钟,想不出来解法的话直接看别人的答案。看懂思路就行了,甚至自己写一遍都没必要,因为比较浪费时间。

笔试的时候最怕的是没思路,所以把各种题型都过目一下,起码心里不会慌,只要有思路,平均一道题二三十分钟搞定还是不难的

mirrors / labuladong / Fucking Algorithm · GitCode

推荐:labuladong 的算法小抄 | labuladong 的算法小抄

突击笔试计划

mirrors / youngyangyang04 / leetcode-master · GitCode

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值