题解 | #队列消数#

队列消数

https://www.nowcoder.com/practice/48f6e451ff52440798067b77dc5ea95b

题目链接

买票需要的时间

题目描述

n 个人在一个队列里购买电影票,每个人要购买的票数由数组 tickets 表示,tickets[i] 是第 i 个人要买的票数。第 k 个人是你特别关心的人。

整个过程遵循以下规则:

  1. 每个人轮流从队首购买一张票,这个过程耗时 1 秒。
  2. 买完一张票后,如果这个人还需要购买更多的票,他会移动到队尾,重新排队。
  3. 如果这个人已经买完了他需要的所有票,他会离开队列。

你需要计算并返回第 k 个人买完他所有票总共需要的时间。

示例 输入: tickets = [1,1,4,5,1,4], k = 2 输出: 13

解题思路

虽然这个问题可以用一个队列来直接模拟,但这样做效率不高。一个更优的解法是直接通过一次遍历来计算总时间。

我们可以把总时间看作是所有人购买行为耗时的总和,直到第 k 个人完成任务为止。我们以第 k 个人需要购买的票数 tickets[k] 为基准,分析队列中每个人(包括他自己)会完整地排队多少轮。

  1. 对于排在第 k 个人前面的人(包括第 k 个人自己,即索引 i <= k:

    • 在第 k 个人买完所有票之前,这些人至少会和第 k 个人一样,有机会排满 tickets[k] 轮。
    • 如果这个人 i 本身需要的票数 tickets[i] 少于 tickets[k],那么他会在 tickets[i] 轮后提前离场。
    • 因此,这类人耗费的时间是 min(tickets[i], tickets[k]) 秒。
  2. 对于排在第 k 个人后面的人(即索引 i > k:

    • 这些人总是比第 k 个人晚一步。当第 k 个人进行第 tickets[k] 轮购买并离场时,这一轮还没有轮到他们。
    • 所以,他们最多只会完整地排 tickets[k] - 1 轮。
    • 同样,如果他们自己需要的票数 tickets[i]tickets[k] - 1 还少,他们会更早离场。
    • 因此,这类人耗费的时间是 min(tickets[i], tickets[k] - 1) 秒。

我们只需要遍历整个 tickets 数组,根据上述两种情况累加每个人的耗时,就能得到最终的总时间。

代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param tickets int整型vector 
     * @param k int整型 
     * @return int整型
     */
    int timeRequiredToBuy(vector<int>& tickets, int k) {
        int time = 0;
        int n = tickets.size();
        for (int i = 0; i < n; ++i) {
            if (i <= k) {
                time += min(tickets[i], tickets[k]);
            } else {
                time += min(tickets[i], tickets[k] - 1);
            }
        }
        return time;
    }
};
import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param tickets int整型一维数组
     * @param k int整型
     * @return int整型
     */
    public int timeRequiredToBuy(int[] tickets, int k) {
        int time = 0;
        int n = tickets.length;
        for (int i = 0; i < n; i++) {
            if (i <= k) {
                time += Math.min(tickets[i], tickets[k]);
            } else {
                time += Math.min(tickets[i], tickets[k] - 1);
            }
        }
        return time;
    }
}
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param tickets int整型一维数组
# @param k int整型
# @return int整型
#
class Solution:
    def timeRequiredToBuy(self , tickets: List[int], k: int) -> int:
        time = 0
        n = len(tickets)
        for i in range(n):
            if i <= k:
                time += min(tickets[i], tickets[k])
            else:
                time += min(tickets[i], tickets[k] - 1)
        return time

算法及复杂度

  • 算法:单次遍历、数学计算
  • 时间复杂度,其中 Ntickets 数组的长度,因为我们只需要遍历一次数组。
  • 空间复杂度,我们没有使用额外的、随输入大小增长的存储空间。
全部评论

相关推荐

10-19 10:28
已编辑
成都理工大学 后端工程师
团孝子已上线feeling:面了很多家公司,能感受到目前只有小公司+外包喜欢问八股。大厂虽然也问八股,但是是从实习、项目中进行提问,并且大厂会问很深,面试官也会对你的回答进行思考➕追问,所以准备大厂面试前一定要备好相关资料。对于算法,我做的是codetop前100+力扣hot100+力扣高频150,面试中实感hot100就足够,基本上只要是hot100就秒答。对于项目和八股,我做的也是烂大街的星球项目,八股则是看小林和问ai,自己也写了很多技术博客和画了很多思维导图,并且自己也尝试用嘴巴说出来,不只停留于纸面。运气也很重要,必须要让面试官/HR看到简历才行,所以建议投递时间是下午两点。tl:第一岗位9.9&nbsp;投递9.10&nbsp;一面(一面评价:最近见过最强的大三,结束五分钟后约二面,都晚上九点了不下班吗)9.11&nbsp;二面(三道算法a出两道,反问评价:经验不够等横向,我实习生要啥经验)9.21挂(实习时间过短+其他原因,想要一年实习的,为什么不招个正职)第二岗位10.10投递10.11约面(主管打电话,说看到我之前投递记录了想要我挂qa职进去干后端,同意)10.14&nbsp;一面(无八股,主动说确实很强,意愿很强)10.16&nbsp;oc其余,友邦,东软,东华,惠择,用友oc已拒京东测开一面挂(投后端被测开捞)腾讯测试已拒(投后端被测开捞)ps:表扬惠择的主管面,没怎么问技术(可能是一面面试官沟通过了),全程一起讲大道理,解答了心中很多疑惑,也告诉我以面试官角度来看怎么选候选人,如果可以下次一定选惠择
HeaoDng:美团好像可以触发一面通
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务