前端笔试题系列

984 阅读2分钟

提供可笔试考察的题目。代码阅读以代码手写

JSON.parse数组

JSON.parse("[[[2],45,6,7],6,7,8]")

// 1
function jsonParse (opt) {
 return eval(`(${opt})`);
}

// 2
var json = (new Function('return ' + jsonStr))();

// 3
function jsonParse (json) {
  var rx_one = /^[\],:{}\s]*$/;
  var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
  var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
  if (rx_one.test(json.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, ""))) {
    return eval(`(${json})`);
  }
}
 

实现 cache函数

function cache(fn){
  // TO-DO
  var res ={}
  return function(){
    var arg = arguments[0]
    console.log(arg)
    if(res[arg]){
      console.log('走的缓存')
      return res[arg]
    }else{
      res[arg] = fn.call(null,arg)
      return res[arg]
    }
    
  }
  
}

function complexCal(a){
  //这里有复杂计算
  return a
}

var combine  = cache(complexCal)

combine(1)
combine(2)
combine(1)

股票

// maxProfit([9,1,6,3,6,4] )
var maxProfit = function (prices) {
  let profit = 0; // 收益
  for (let i = 1; i < prices.length; i++) {
    // 今天和昨天的差价 差价大于0 才能算是收益不然就是赔钱
    profit += Math.max(0, prices[i] - prices[i - 1]);
  }
  return profit;
};

大数相加

//  缺少负数的考虑
let a = "9007199254740991";
let b = "1234567899999999999";

function add(a ,b){
   //取两个数字的最大长度
   let maxLength = Math.max(a.length, b.length);
   //用0去补齐长度
   a = a.padStart(maxLength , 0);  //"0009007199254740991"
   b = b.padStart(maxLength , 0);   //"1234567899999999999"
   //定义加法过程中需要用到的变量
   let t = 0;
   let f = 0;   //"进位"
   let sum = "";
   for(let i=maxLength-1 ; i>=0 ; i--){
      t = parseInt(a[i]) + parseInt(b[i]) + f;
      f = Math.floor(t/10);
      sum = t%10 + sum;
   }
   if(f == 1){
      sum = "1" + sum;
   }
   return sum;
}

回文子串

var countSubstrings = function(s) {
    // dp[i][j] 表示第i个数到第j个数是否为回文串
    // dp[i][j] = (s[i] === s[j] && (j - i <= 2 || dp[i + 1][j - 1]))
    // 依次以i开头的字符串,判断从i j 之间是否有回文串
    let dp = new Array(s.length).fill().map(() => new Array())
    console.log(dp)
    let res = 0
    for (let i = s.length - 1; i >= 0; i--) {
        for (let j = s.length - 1; j >= i; j--) {
            if (
                s[i] === s[j] && 
                (j - i <= 2 || dp[i + 1][j - 1])
            ) {
                dp[i][j] = true;
            }
            if (dp[i][j]) res++;
        }
    }
    console.log(dp)
    return res;
};


console.log(countSubstrings('abac'))

矩阵:左上角到右下角最近距离

var minPathSum = function(grid) {
    console.log(grid)

    for (let i = 1; i < grid.length; i++) {

        grid[i][0] = grid[i-1][0] + grid[i][0]
    }
    for (let i = 1; i < grid[0].length; i++) {
        grid[0][i] = grid[0][i-1] + grid[0][i]
    }
    console.log(grid)
    for (let i =1; i < grid.length; i++) {
        for (let j = 1; j < grid[0].length; j++) {

            grid[i][j] = Math.min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
        }
    }
    console.log(grid)
    
    return grid[grid.length-1][grid[0].length-1]
    
};

const arr = [  [1, 3, 1],
  [1, 5, 1],
  [4, 2, 1],
];

console.log(minPathSum(arr))

八皇后变种:给定一个8x8的棋盘, 上面有若干个车 写一个函数检查这些车有没有互相攻击的情况

8x8棋盘,要求随机生成一张棋盘,值分别为1、0,1代表有车,0代表没车,并返回这张棋盘是否存在相互攻击的情况。

假设当前场景没有互相攻击,那么最多还能放置多少辆小车?有多少种放法?

let arr = [
  [0, 0, 0, 1, 1, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 0, 0, 0, 0],
];

function checkConflict(arr) {
  let resRow = [];
  let resCol = [];

  // 遍历两次 寻找同一行  同一列
  for (let index = 0; index < 8; index++) {
    const row = arr[index].reduce((pre, item, i) => {
      if (item === 1) {
        return [...pre, [i, index]];
      }
      return pre;
    }, []);
    if (row.length > 1) {
      resRow = [...resRow, ...row];
    }
  }

  for (let jndex = 0; jndex < 8; jndex++) {
    let _arr = Array.from({ length: 8 }).map((_, index) => {
      return arr[index][jndex];
    });
    const col = _arr.reduce((pre, item, i) => {
      if (item === 1) {
        return [...pre, [jndex, i]];
      }
      return pre;
    }, []);
    if (col.length > 1) {
      resCol = [...resCol, ...col];
    }
  }

  return {
    resRow,
    resCol,
  };
}

console.log(checkConflict(arr));


// 已知放车的行不参与遍历,每一个的落点满足两个条件 :1,行上没有车 2 列上没有车 。










八皇后变种:8x8棋盘,随机有N个车,要求获取到不被车攻击的所有点。

//  八皇后变种:8x8棋盘,随机有N个车,要求获取到不被车攻击的所有点。

// 从车开始 遍历每一个车的 上下 左右方向。把所有能攻击的坐标标记出来,剩下的就是不能被攻击的

function a(array) {
  const allMap = {};
  const utilArr = Array.from({ length: 8 }).fill(0);

  function map(fn) {
    for (let rowI = 0; rowI < array.length; rowI++) {
      for (let colI = 0; colI < array[0].length; colI++) {
        fn(rowI, colI);
      }
    }
  }
  map((rowI, colI) => {
    // 保存所有坐标的建值对
    allMap[`${rowI}${colI}`] = false;
  });
  map((rowI, colI) => {
    // 该子是车    行列上的都标记为true
    if (array[rowI][colI] === 1) {
      utilArr.forEach((_, index) => {
        allMap[`${rowI}${index}`] = true;
        allMap[`${index}${colI}`] = true;
      });
    }
  });
  return allMap;
}

console.log(
  a([
    [0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0],
  ])
);

8x8的棋盘上,放置着若干「黑皇后」和一个「白国王」,找出能够攻击国王的皇后

function yy(queens, king) {
  const result = [],
    dd = [      [-1, 0], // 左
      [-1, 1],// 左上
      [0, 1], // 上
      [1, 1], // 右上
      [1, 0], // 右
      [1, -1], // 右下
      [0, -1], // 下
      [-1, -1], // 左下
    ];
  dd.forEach(([dx, dy]) => {
    const temp = fin(dx, dy);
    if (temp) result.push(temp);
  });

  function fin(dx, dy) {
      // 要check的坐标坐标
    let posX = king[0],
      posY = king[1];
    do {
      posX += dx;
      posY += dy;
      // 移动一格后的坐标
      if ( // 坐标上🈶️queen
        queens.find((queen) => {
          return queen[0] === posX && queen[1] === posY;
        })
      ) {
        return [posX, posY];
      }
    } while (posX >= 0 && posX <= 8 && posY >= 0 && posY <= 8);
    return null;
  }
  return result;
}

console.log(
  yy(
    [
      [0, 1],
      [1, 0],
      [4, 0],
      [0, 4],
      [3, 3],
      [2, 4],
    ],
    [0, 0]
  )
);


数组降纬

// 降纬
function flat(arr){
  return  Array.isArray(arr) ? arr.reduce((pre,item)=>([...pre,...flat(item)]),[]) : [arr]
}

console.log(flat([1, [[2], [3, [4]], 5]]))

代码执行

function F() {};
F.a = 100;
F.prototype.b = 10;
let z = new F();
console.log(z.a);  // undefined
console.log(z.b);  // 10
function fun(n, k) {
  console.log(k);
  return {
    fun: function (m) {
      return fun(m, n);
    },
  };
}


var a = fun(0);  // undefined
a.fun(1);        // 0
a.fun(2);        // 0
a.fun(3);        // 0

var b = fun(0).fun(1).fun(2).fun(3);  // undefined 0 1 2
var c = fun(0).fun(1);                // undefined 0
c.fun(2);                             // 1
c.fun(3);                             // 1

树遍历

深度遍历-递归

var recursiveTraverse = function (node, action) {
	if (!node || !node.children) { return; }
	action(node.value);
	node.children.forEach(function(item, index) {
		recursiveTraverse(item, action);
	});
}
// 递归实现
recursiveTraverse(tree, console.log);


var nonRecursiveDepthFirstTraversal = function (node, action) {
	if (!node || !node.children) { return; }
	var _stack = []; // 借助一个栈
	_stack.unshift(node);
	while (_stack.length) {
		let _curNode = _stack.shift(); // 推出栈顶元素
		action(_curNode.value);
		// 将子节点依次放入到栈顶
		// _curNode.children.forEach(function (item, index) {
		// 	_stack.unshift(item);
		// })
		if (_curNode.children.length) {
			_stack = _curNode.children.concat(_stack);
		}
	}
}
// 非递归深度优先遍历
nonRecursiveDepthFirstTraversal(tree, console.log);


var nonRecursiveWidthFirstTraversal = function (node, action) {
	if (!node || !node.children) { return; }
	var _queue = []; // 借助一个队列
	_queue.push(node);
	while (_queue.length) {
		let _curNode = _queue.shift(); // 推出队头元素
		action(_curNode.value);
		// 将子节点依次推入队列中
		// _curNode.children.forEach(function (item, index) {
		// 	_queue.push(item);
		// })
		if (_curNode.children.length) {
			_queue = _queue.concat(_curNode.children);
		}
	}
}
// 非递归宽度优先遍历
nonRecursiveWidthFirstTraversal(tree, console.log);