个人感觉这一周的题目在难度和出题水平上都要相比上一周的逊色不少。
第一题:哥德巴赫猜想
由于原题的第一题实在是太无聊了,所以我索性给改成了用代码实现哥德巴赫猜想。关于什么是哥德巴赫猜想,可以点击上面的标题链接观看B站的视频介绍。代码实现如下:
const goldbach = (max) => {
let primeArr = [];
let evenArr = [];
let failArr = [];
const isPrime = (num) => {
let mid = Math.floor(Math.sqrt(num));
let flag = true;
for (let index = 2; index <= mid; index++) {
if (num % index === 0) {
flag = false;
break;
}
}
return flag;
};
const decompose = (even) => {
for (const prime of primeArr) {
let remain = even - prime;
if (remain < prime) {
break;
} else if (primeArr.includes(remain)) {
return [prime, remain];
}
}
return null;
}
for (let index = 2; index <= max; index++) {
if (index > 2 && index % 2 === 0) {
let factor = decompose(index);
if (factor) {
evenArr.push([index, ...factor]);
} else {
failArr.push(index);
}
} else if (isPrime(index)) {
primeArr.push(index);
}
}
return {
primeArr,
evenArr,
failArr,
};
}
let now = Date.now();
let res = goldbach(1e4);
console.log(`NASA: ${Date.now() - now}ms`);
console.log('NASA: primeArr.length', res.primeArr.length);
console.log('NASA: evenArr.length', res.evenArr.length);
console.log('NASA: failArr.length', res.failArr.length);
第二题:灯泡开关 III
解题思路
这一题其实你没有必要去纠结当新的灯泡点亮后位于它左边的灯泡的点亮情况,这么想的话就太麻烦了,其实你只需要抓住两个index就可以了。这两个index分别是从左往右的第一个未点亮灯泡的leftIndex(base-0)以及从右往左的第一个已点亮灯泡的rightIndex(base-1),只要leftIndex等于rightIndex就说明当前已点亮的灯泡都是蓝色的。代码如下所示:
var numTimesAllBlue = function (light) {
let leftIndex = 0;
let rightIndex = -1;
let blueCount = 0;
let bulbArr = Array(light.length).fill(0);
for (const bulb of light) {
bulbArr[bulb - 1] = 1;
rightIndex = Math.max(rightIndex, bulb);
if (bulbArr[leftIndex]) {
while (bulbArr[++leftIndex]) continue;
if (leftIndex === rightIndex) {
blueCount++;
}
}
}
return blueCount;
};
let light = [2, 1, 3, 5, 4];
console.log(`NASA: ${numTimesAllBlue(light)}`);
第三题:通知所有员工所需的时间
解题思路
这一题虽然题目描述贼拉长,但是要做的事情却十分简单,只需要把树结构构造好,记录下每个节点抵达子节点的权值(也就是通知时长),再用递归的方式求得所有抵达叶子节点的路径的权值之和中最大的那一个值就好了。代码如下:
var numOfMinutes = function (n, headID, manager, informTime) {
function TreeNode(index, time = 0) {
this.index = index;
this.time = time;
this.sub = [];
}
const getTree = (parent) => {
for (let index = 0; index < manager.length; index++) {
let parentIndex = manager[index];
if (parentIndex === parent.index) {
let node = new TreeNode(index, informTime[index]);
parent.sub.push(node);
getTree(node);
}
}
}
const getTime = (node) => {
return node.sub.length && (node.time + Math.max(...node.sub.map(getTime)));
};
const root = new TreeNode(headID, informTime[headID]);
getTree(root);
return getTime(root);
};
let n = 15, headID = 0, manager = [-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6], informTime = [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
console.log(`NASA: ${numOfMinutes(n, headID, manager, informTime)}`);
第四题:T 秒后青蛙的位置
这一题其实也很简单,没有什么太多好说的,解题思路跟第三题非常类似,也是先构造树形结构,然后算出抵达每一个节点的权值(也就是概率值),最后拿到目标节点的概率值就好了。不过,我的代码实现里用了一点小小的技巧,这个就留给读者你去探索一番啦
var frogPosition = function (n, edges, t, target) {
function TreeNode(value, level, parent = null) {
this.value = value;
this.level = level;
this.parent = parent;
this.prob = 0;
this.sub = [];
}
const getTree = (edges) => {
let map = {};
let root;
for (const item of edges) {
let parent = item[0];
let child = item[1];
map[parent] = map[parent] || new TreeNode(parent);
map[child] = map[child] || new TreeNode(child);
map[parent].sub.push(map[child]);
map[child].parent = map[parent];
}
for (const item of Object.values(map)) {
do {
root = item.parent;
} while (root);
root = item;
root.prob = 1;
root.level = 0;
break;
}
return {
root,
map,
};
}
const infoTree = (node) => {
if (!node.sub.length) return;
let prob = 1 / node.sub.length;
for (const child of node.sub) {
child.prob = prob * node.prob;
child.level = node.level + 1;
infoTree(child);
}
}
let { root, map } = getTree(edges);
infoTree(root);
target = map[target];
return target.level <= t ? target.prob : 0;
};
let n = 7, edges = [[1, 2], [1, 3], [1, 7], [2, 4], [2, 6], [3, 5]], t = 5, target = 6;
console.log(`NASA: ${frogPosition(n, edges, t, target)}`);