华为OD --- 流浪地球

华为OD --- 流浪地球

  • 题目
  • 独立实现
    • 基本思路
    • 代码实现
  • 其他答案
    • 实现思路
    • 代码实现

题目

华为OD --- 流浪地球_第1张图片

独立实现

基本思路

1、首先把题目给出的启动机器初始化成数组,
2、用for循环模拟每隔1s更新这个初始化数组的前后两个机器. (源码中的updateTimeCount函数)
3、for循环每次循环后会检查当前启动机器列表是否全部启动(源码中的chechList函数)并保存当前的启动机器列表(preStartMachineList)
4、如果机器没有全部启动 重复 2 - 3 流程
5、如果机器全部启动了 拿preStartMachineList中保存的值去和0 - n-1的数组做差值比较,那么这个差值肯定就是最后启动的机器列表

代码实现

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();

const readline = async () => (await iter.next()).value;

void (async function () {
    // 保存总数和启动数
    const [allCount, startCount] = (await readline()).split(" ");
    // Write your code here
    let inputIndex = 0;
    // 记录发动机启动时间和序号的列表
    let machineInfo = [];
    while (inputIndex < Number(startCount)) {
        const inputLine = await readline();
        const [startTime, startIndex] = inputLine.split(" ");

        if (!machineInfo[startTime]) {
            machineInfo[startTime] = [];
        }
        machineInfo[startTime].push([startIndex]);
        inputIndex++;
    }

    machineInfo.filter((item) => item);
    // 用来保存全部启动之前的机器列表 和全部启动之后的机器列表之差就是最后启动的机器数
    let preStartMachineList = [];

    // console.log("machineInfo", machineInfo);

    const updateTimeCount = (currentIndex) => {
        // console.log("resultList", JSON.stringify(resultList));
        resultList.forEach((result) => {
            // 小于当前时间戳,需要更新时间
            if (result && result.timeCount < currentIndex) {
                const steps = currentIndex - result.timeCount;

                result.startMachine = result.startMachine.map((item) => {
                    const centerNumber = item[Math.floor(item.length / 2)];
                    return [
                        centerNumber - steps < 0
                            ? allCount - Math.abs(centerNumber - steps)
                            : centerNumber - steps,
                        ...item,
                        centerNumber + steps >= allCount
                            ? 0 + Math.abs(allCount - (centerNumber + steps))
                            : centerNumber + steps,
                    ];
                });
                // result.timeCount = currentIndex;
            }
        });
        // console.log("updateTimeCount", resultList?.[0]?.startMachine);
    };

    const chechList = (list) => {
        const startedMachine = Array.from(
            new Set(
                list
                    .map((item) => item.startMachine)
                    .flat(Number.MAX_SAFE_INTEGER)
            )
        );

        // console.log("checklist", startedMachine);
        if (startedMachine.length >= allCount) {
            return true;
        } else {
            preStartMachineList = startedMachine;
            return false;
        }
    };

    const resultList = [];
    // console.log("machineInfo", machineInfo);
    for (let i = 0; i < allCount; i++) {
        if (machineInfo[i]) {
            resultList.push({
                timeCount: i,
                startMachine: machineInfo[i].map((item) => [Number(item)]),
            });
        }
        updateTimeCount(i);

        // 全部启动完成 后续循环跳过
        if (chechList(resultList)) {
            // console.log("finish", preStartMachineList);
            const lastStartMachineList = [];
            for (let j = 0; j < allCount; j++) {
                if (!preStartMachineList.includes(j)) {
                    lastStartMachineList.push(j);
                }
            }
            console.log(lastStartMachineList.length);
            console.log(lastStartMachineList.join(" "));
            break;
        }
    }
})();

其他答案

实现思路

1、初始化一个项数为n的数组 初始化为无限大,表示机器的启动时间
2、通过两次遍历找出所有机器的启动时间 以0 2 0 6为例
3、最后得出的数组为[2,1,0,1,2,1,0,1]
3、最大的数就是最晚启动时间,输出最大数的个数以及index即可

代码实现

	const rl = require("readline").createInterface({ input: process.stdin });
	var iter = rl[Symbol.asyncIterator]();
	const readline = async () => (await iter.next()).value;

void (async function () {
    //   保存总发动机数量和首次启动的发动机数量
    const [allCount, startCount] = (await readline()).split(" ").map(Number); // allCount = 8; startCount = 2

    const startTimeList = new Array(allCount).fill(Number.MAX_SAFE_INTEGER); // 初始化一个机器启动时间数组 这个数组有8项 [最大值,最大值,最大值....] 因为最开始的启动时间是未知的,所以这里我们初始化为最大值,表示机器启动需要无限大时间

    let inputIndex = 0;
    do {
        // 在这里读取机器启动时间,比如0,2 表示机器2在第0秒启动
        const [startTime, startIndex] = (await readline())
            .split(" ")
            .map(Number);
        startTimeList[startIndex] = startTime;
        inputIndex++;
    } while (inputIndex < startCount);
    //  所以经过读取输入(0,2) (0,6)之后的startTimeList为[最大值,最大值,0,最大值,最大值,最大值,0,最大值]

    //   1、这里植入下对环数据结构最小启动时间的理解,可以看到第2号机器和第6号机器都是从0秒启动
    //   2、从第5号(实际上从任何机器开始都可以,随便举的)机器的启动时间开始分析,0 1 2 3 4 5 6 7
    //   3、因为是环形结构,所以机器的启动时间实际就看和首批机器启动时间的绝对值取小值就行了 比如第5号机器距离2号机器 有两种方向 2 3 4 5需要3秒时间(5-2) 另一种走法需要2 1 0 7 6 5 需要5秒时间8-(5-2) 所以最终取到的是3和5之间的小值3秒
    //   4、但是因为6号机器也是第0秒启动 所以5号机器从6号机器出发的路径是 6 5 方向1需要6 5 1s(6-5)方向2 6 7 0 1 2 3 4 5 需要7秒(8-(6-5)) 取小值 1s
    //   5、综上取到的5号机器的实际启动时间是1s和3秒之间的小值 所以5号机器最终的启动时间是1s.

    // 按照这个方法类推,可以推出所有机器的启动时间
    for(let i=0;i<allCount;i++){
        for(let j=0;j<allCount;j++){
            // 方向1需要的启动时间
            const direction_left = Math.abs(j - i)
            // 方向2需要的启动时间
            const direction_right = allCount - Math.abs(j - i)
            // 取小值
            const minDistance = Math.min(direction_left, direction_right)
            startTimeList[i] = Math.min(startTimeList[i], startTimeList[j] + minDistance)
        }
    }

    const maxDistance = Math.max(...startTimeList)
    const resultList = []
    startTimeList.forEach((item, index) => {
        if(item === maxDistance) resultList.push(index)
    })

    console.log(resultList.length)
    console.log(resultList.join(' '))

})();

你可能感兴趣的:(华为OD,前端,javascript,华为od)