You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中优化演出门票购买算法?算法问题解析

演唱会购票时间计算:Node.js 优化方案

Hey 朋友,咱们来一步步解决这个演唱会门票的时间计算问题,从直观的模拟方法到高效的数学优化方案都给你理清楚~

首先得把问题的规则再明确下:

售票规则:每人每次只能买1张票,要是想买多张,必须重新排到队尾;杰西现在在队伍里,需要买N张票,给定所有购票者的初始购票需求列表,得算出杰西买完所有票总共花了多少时间。


先说说最直观的暴力模拟法(适合小数据量)

最容易想到的就是直接模拟整个排队过程:

  • 用队列来模拟队伍,每一轮挨个处理每个购票者:
    • 如果这个人还有票要购买,时间加1,把他的购票需求减1;
    • 如果这个人是杰西,而且他的需求已经减到0了,直接返回当前时间就行;
    • 要是这个人还有剩余需求,就把他放到队尾重新排队。

不过这种方法有个问题:如果队伍里人特别多,或者每个人要买的票特别多,那模拟的轮次会超级多,性能会拉胯。比如要是有1000个人每人买1000张票,那得循环100万次,想想都慢。

暴力法的Node.js实现

function calculateTimeBruteforce(people, jesseIndex) {
    let time = 0;
    const queue = [...people];
    let jesseRemaining = queue[jesseIndex];
    let currentJessePos = jesseIndex;

    while (jesseRemaining > 0) {
        const currentPerson = queue.shift();
        if (currentPerson > 0) {
            time++;
            // 处理杰西的剩余票数
            if (currentJessePos === 0) {
                jesseRemaining--;
                if (jesseRemaining === 0) {
                    return time;
                }
                // 杰西买完一张,排到队尾,新位置是当前队列长度(因为刚shift了一个元素)
                currentJessePos = queue.length;
            } else {
                currentJessePos--;
            }
            // 还有需求的话,放回队尾
            queue.push(currentPerson - 1);
        } else {
            // 这个人已经买完了,不用再排队,调整杰西的位置
            if (currentJessePos > 0) {
                currentJessePos--;
            }
        }
    }
    return time;
}

// 测试示例:队伍是[2,3,2],杰西在第2个位置(索引1),需要买3张
console.log(calculateTimeBruteforce([2,3,2], 1)); // 输出7,和实际流程一致

重点来啦:O(n)时间的优化方案

其实我们完全不用模拟每一轮,用数学推导就能直接算出总时间,效率直接拉满!

核心思路是:计算杰西买完所有票的过程中,每一个购票者总共会占用多少时间,把这些时间加起来就是总耗时。

具体分三种情况:

  1. 杰西前面的人:他们在杰西买完所有票的过程中,最多能买min(自己的需求, 杰西需要的票数)次——因为杰西买k张要排k次队,前面的人每一轮都能买,直到自己买完或者杰西买完。
  2. 杰西自己:肯定是买k次,贡献k单位时间。
  3. 杰西后面的人:他们最多能买min(自己的需求, 杰西需要的票数-1)次——因为杰西在第k次买完票之后就结束了,后面的人在第k轮时杰西已经完成购票,不会再轮到他们。

这样我们只需要遍历一次购票列表,就能算出总时间,不管数据量多大,都能瞬间出结果。

优化方案的Node.js实现

function calculateTimeOptimized(people, jesseIndex) {
    const jesseNeed = people[jesseIndex];
    let totalTime = 0;

    for (let i = 0; i < people.length; i++) {
        if (i < jesseIndex) {
            // 前面的人:最多参与jesseNeed轮
            totalTime += Math.min(people[i], jesseNeed);
        } else if (i === jesseIndex) {
            // 杰西自己的k次
            totalTime += jesseNeed;
        } else {
            // 后面的人:最多参与jesseNeed-1轮
            totalTime += Math.min(people[i], jesseNeed - 1);
        }
    }

    return totalTime;
}

// 同样测试示例
console.log(calculateTimeOptimized([2,3,2], 1)); // 输出7,和暴力法结果一致

验证一下逻辑

拿示例[2,3,2],杰西需要3张票:

  • 前面的人需要2张,贡献min(2,3)=2;
  • 杰西自己贡献3;
  • 后面的人需要2张,贡献min(2,3-1)=2;
    总时间2+3+2=7,和模拟的实际流程完全匹配:
  • 第1轮:所有人各买1张,时间+3;
  • 第2轮:所有人各买1张,时间+3(累计6);
  • 第3轮:轮到杰西买最后1张,时间+1(累计7),结束。

为啥优化方案更牛?

如果遇到极端情况,比如10万人每人买100万张票,暴力模拟法会直接超时,而优化方案只需要遍历10万次,眨眼就能出结果,性能差距不是一星半点。

内容的提问来源于stack exchange,提问作者Akhilesh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:57:18