Bootstrap

华为od机考

两道一星+一道二星(限时150min)
机考parseInt还是没搞懂,姑且就按记录一下自己平时的实现方法做了一下,可能与标准答案有出入,欢迎指正。
1、停车场停车的最少数量

function cars(arr) {
  if (arr[arr.length - 1] === 1) {
    return portCars(arr, 1, 0);
  }
  return portCars(arr, 0, 0);
}

function portCars(arr, count, more) {
  // 小车数量
  // 单个1 ————只有1辆车;
  // 连续二个1 ———— 可能有1辆车或2辆车
  // 连续三个1 ———— 可能有1、2、3辆车
  // 数组是一维数组
  // 取最大的连续,有点像斐波那契

  // 递归,统计最小车可能

  // 边界,为0
  if (!arr) return count;

  for (let i = 0; i < arr.length; i++) {
    let num = arr.shift();
    // 找到1,看是否连续,用参数传递记忆,闭包,连续3个之内都有效;
    if (num === 1 && more < 3) {
      return portCars(arr, count, ++more);
    } else {
      // 找到0, more重新计数
      return portCars(arr, ++count, 0);
    }
  }
  return count;
}
console.log(cars([1,0,1,0]));

2、内存池分配

// 1、分配 > 申请;粒度尽可能小;不能拆分
// 2、时间顺序
// 3、可true无false

// 粒度大小:数量
// 表述输入的变量参数
function deliver(arr, applyArr) {
    // 边界判断, 需要与输入结合
    const res = [],newArr = [];

    // 只处理一次内存池数据
    for (let y = 0; y < arr.length; y++) {
        newArr.push(arr[y].split(":"));
    }

    // 按申请顺序匹配
    applyArr.forEach((applyValue) => {
      // 从小到大,优先匹配粒度小的
      for (let i = 0; i < newArr.length; i++) {
        const element = newArr[i];
        // 内存大小符合且内存数量存在
        if (applyValue <= element[0] && element[1]) {
          // 删去数量
          element[1] = element[1]--;
          // 记录结果
          res.push(true);
        }
      }
      // 对单个申请的内存,为匹配到的
      res.push(false);
    });

    return res;
}

3、猜密码

// 都是数字,都不重复
// 给出范围、最小数字数量??
// 可能的组合:1、数字在范围内的;2、数字和字母分别递增排序;3、每个数字数量大于最小数字数量;4、空返回None
// 按字典序输出


// 同:类似洗扑克牌解法,在n张里抽
function guessNum(arr, minRange) {
  // 边界:重复、空、范围不够
  if (arr.length < minRange || Array.from(new Set(arr)).length !== arr.length) {
    return;
  }
  if (!arr) return "None";

  // 思路:遍历删n个元素,递归到单次目标范围,剩余数组sort
  let res = [];
  // 1、从最小数字范围开始
  for (let range = minRange; range < arr.length; range++) {
    // 1-1、要删去多少个元素
    let diff = arr.length - range;

    // 1-2、遍历删去所有可能组合
    for (let j = 0; j < arr.length; j++) {
      let restArr = iterator(arr, diff, j);
      // 2、对剩余数组,按递增排序后,得到单次有效组合,加入结果
      res.push(restArr.sort((a, b) => a - b));
    }
    // 1-3、递归组合
    function iterator(arr, diff, j) {
      // 完成目标范围的递归,返回组合后的数组
      if (!diff) return arr;
      // 深拷贝数组
      let cloneArr = [...arr];
      // 删除单个元素后
      cloneArr.splice(j, 1);
      return iterator(cloneArr, diff--);
    }
  }
  // 3、结果按字典序排序输出
  // 规律:长度同,比较前n个最小的
  // 前面是从最小范围开始,得到的res数组里的元素长度是由小到大的
  // 递归组合是按由小到大组合去删去某个元素,得到的剩余数组应该是由大到小
  // 那么在长度变化的一段起切片,翻转数组后再拼接即可
  for (let k = 0; k < res.length - 1; k++) {
    // 长度变化
    if (res[k].length !== res[k+1].length) {
        // 切片后拼接
        let cutArr = res.splice(0,k+1).reverse()
        res = cutArr.concat(...res)
    }
  }
  return res;
}
;