两道一星+一道二星(限时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;
}