LeetCode 2073: Time Needed to Buy Tickets (Queue Simulation by Rounds)
LeetCode 2073QueueSimulationToday we solve LeetCode 2073 - Time Needed to Buy Tickets.
Source: https://leetcode.com/problems/time-needed-to-buy-tickets/
English
Problem Summary
Given tickets[i] as the number of tickets person i wants, people buy one ticket per turn from left to right and rejoin the queue if they still need more. Return how many seconds until person k finishes.
Key Insight
Person k buys exactly tickets[k] tickets, so there are exactly that many rounds involving people before/at k. For each person:
- If i <= k, they can buy at most tickets[k] times.
- If i > k, they can only buy at most tickets[k] - 1 times (because process stops immediately when k gets the final ticket).
Formula
Add min(tickets[i], tickets[k]) for i <= k, and
add min(tickets[i], tickets[k] - 1) for i > k.
Complexity Analysis
Time: O(n).
Space: O(1).
Common Pitfalls
- Forgetting that people after k get one fewer chance.
- Over-simulating with an explicit queue, which is valid but unnecessary.
- Off-by-one when tickets[k] = 1.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int timeRequiredToBuy(int[] tickets, int k) {
int need = tickets[k];
int ans = 0;
for (int i = 0; i < tickets.length; i++) {
if (i <= k) {
ans += Math.min(tickets[i], need);
} else {
ans += Math.min(tickets[i], need - 1);
}
}
return ans;
}
}func timeRequiredToBuy(tickets []int, k int) int {
need := tickets[k]
ans := 0
for i, t := range tickets {
if i <= k {
if t < need {
ans += t
} else {
ans += need
}
} else {
cap := need - 1
if t < cap {
ans += t
} else {
ans += cap
}
}
}
return ans
}class Solution {
public:
int timeRequiredToBuy(vector<int>& tickets, int k) {
int need = tickets[k];
int ans = 0;
for (int i = 0; i < (int)tickets.size(); ++i) {
if (i <= k) ans += min(tickets[i], need);
else ans += min(tickets[i], need - 1);
}
return ans;
}
};class Solution:
def timeRequiredToBuy(self, tickets: List[int], k: int) -> int:
need = tickets[k]
ans = 0
for i, t in enumerate(tickets):
if i <= k:
ans += min(t, need)
else:
ans += min(t, need - 1)
return ans/**
* @param {number[]} tickets
* @param {number} k
* @return {number}
*/
var timeRequiredToBuy = function(tickets, k) {
const need = tickets[k];
let ans = 0;
for (let i = 0; i < tickets.length; i++) {
if (i <= k) {
ans += Math.min(tickets[i], need);
} else {
ans += Math.min(tickets[i], need - 1);
}
}
return ans;
};中文
题目概述
给定数组 tickets[i] 表示第 i 个人还要买几张票。队列从左到右,每秒当前人买一张,若还没买完就排到队尾。求第 k 个人买完所需秒数。
核心思路
第 k 个人总共会买 tickets[k] 次。于是:
- 对于 i <= k 的人,最多能参与 tickets[k] 轮。
- 对于 i > k 的人,在 k 买到最后一张后流程立刻结束,所以最多只能参与 tickets[k]-1 轮。
计数公式
对 i <= k 累加 min(tickets[i], tickets[k]);
对 i > k 累加 min(tickets[i], tickets[k]-1)。
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(1)。
常见陷阱
- 忽略 k 之后的人要少算一轮。
- 用完整队列逐秒模拟,代码更长且没必要。
- 在 tickets[k]=1 时出现边界 off-by-one。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int timeRequiredToBuy(int[] tickets, int k) {
int need = tickets[k];
int ans = 0;
for (int i = 0; i < tickets.length; i++) {
if (i <= k) {
ans += Math.min(tickets[i], need);
} else {
ans += Math.min(tickets[i], need - 1);
}
}
return ans;
}
}func timeRequiredToBuy(tickets []int, k int) int {
need := tickets[k]
ans := 0
for i, t := range tickets {
if i <= k {
if t < need {
ans += t
} else {
ans += need
}
} else {
cap := need - 1
if t < cap {
ans += t
} else {
ans += cap
}
}
}
return ans
}class Solution {
public:
int timeRequiredToBuy(vector<int>& tickets, int k) {
int need = tickets[k];
int ans = 0;
for (int i = 0; i < (int)tickets.size(); ++i) {
if (i <= k) ans += min(tickets[i], need);
else ans += min(tickets[i], need - 1);
}
return ans;
}
};class Solution:
def timeRequiredToBuy(self, tickets: List[int], k: int) -> int:
need = tickets[k]
ans = 0
for i, t in enumerate(tickets):
if i <= k:
ans += min(t, need)
else:
ans += min(t, need - 1)
return ans/**
* @param {number[]} tickets
* @param {number} k
* @return {number}
*/
var timeRequiredToBuy = function(tickets, k) {
const need = tickets[k];
let ans = 0;
for (let i = 0; i < tickets.length; i++) {
if (i <= k) {
ans += Math.min(tickets[i], need);
} else {
ans += Math.min(tickets[i], need - 1);
}
}
return ans;
};
Comments