MediumArrayDynamic ProgrammingUpdated Sep 2026

983. Minimum Cost For Tickets

Asked at Adobe

Difficulty

Medium

Time

O(365)

Space

O(365)

Pattern

Array

Companies

1

Problem

You know in advance which days of the year you will take the train. Those days are given as days, a sorted list of day numbers (1 to 365). You must buy tickets so that every listed day is covered.

There are three ticket types: a 1-day pass costs costs[0], a 7-day pass costs costs[1], and a 30-day pass costs costs[2]. A pass bought on some day covers that day plus the next 6 or 29 days, depending on its length. You may buy passes on any day, including days you do not travel.

Return the minimum total cost needed to cover all your travel days. You do not need to cover days you are not traveling, and a pass may cover days outside your list for free.

Cover every travel day cheaply

days1467820These are the only days we must cover; other days arefree to skip1-day pass: covers 1 day, cost 27-day pass: covers 7 days, cost 730-day pass: covers 30 days, cost 15A pass bought on day d covers d, d+1, ... up to itslength
Each pass covers a block of consecutive days, and we want the cheapest set of blocks that touches every marked day.

Constraints

  • ●1 <= days.length <= 365
  • ●1 <= days[i] <= 365
  • ●days is in strictly increasing order
  • ●costs.length == 3
  • ●1 <= costs[i] <= 1000

Examples

Example 1
Inputdays = [1,4,6,7,8,20], costs = [2,7,15]
Output11
WhyBuy a 1-day pass for day 1 ($2). Buy a 7-day pass starting on day 4, which covers days 4 through 10 — that handles 4, 6, 7 and 8 ($7). Buy another 1-day pass for day 20 ($2). Total is 2 + 7 + 2 = 11, and no cheaper mix exists.
Example 2
Inputdays = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]
Output17
WhyA 30-day pass bought on day 1 covers days 1 through 30, which takes care of the first ten days and day 30 ($15). Day 31 is left, so buy a 1-day pass for it ($2). Total is 17. Buying 7-day passes instead would cost more.

Asked At

1 companies
CompanyDifficulty
AdobeMediumView all Adobe questions →

How to Think About It

1

Brute force: for each day, recursively try all three pass options and take the minimum.

2

Use a DP array of size 366 (max days in a year) where dp[i] is the minimum cost to cover days up to day i.

3

If day i is not a travel day, dp[i] = dp[i-1] (no new cost needed).

4

If day i is a travel day, dp[i] = min(dp[i-1] + cost1, dp[max(0,i-7)] + cost7, dp[max(0,i-30)] + cost30).

5

Convert the days list to a set for O(1) lookup. Time O(366), space O(366).

Optimal Approach

Create a boolean set of travel days. Initialize a dp array of size 366 where dp[0] = 0. For each day i from 1 to 365: if not a travel day, dp[i] = dp[i-1]. If it is a travel day, dp[i] = min(dp[i-1] + costs[0], dp[max(0, i-7)] + costs[1], dp[max(0, i-30)] + costs[2]). Return dp[365]. This runs in O(366) time and O(366) space. The key insight is that a pass bought on day i-7 covers day i, so we look back by the pass duration.

DP over the calendar

dp01234567890002222999Day 3 is a travel day: dp[3] = dp[2] + 2 = 2. Day 7 is a travelday: dp[7] = dp[0] + 7 = 7, but dp[6] + 2 = 4 is cheaper, sodp[7] = 4travel day i:dp[i] = min(dp[i-1] + c1, dp[i-7] + c7, dp[i-30] + c30)non-travel day i: dp[i] = dp[i-1]answer = dp[365]
dp[i] is the cheapest way to cover all travel days up to day i. On a travel day we try all three passes and keep the cheapest.
ComplexityTime O(365)Space O(365)We sweep every day of the year once, and each day does a constant amount of work looking back at three earlier days.

What Trips People Up in Real Interviews

1

Clarify the range of days (1 to 365).

2

Ask whether tickets can overlap (yes, and overlapping is allowed for minimum cost).

3

Mention that a set for travel days avoids repeated linear searches.

4

Edge cases: travel on day 1 only, all 365 days are travel days, gaps between travel days.

5

The dp transition considers max(0, i-duration) to handle boundary conditions cleanly.

Solution Code

O(365) time
def mincostTickets(days, costs):
    travel = set(days)
    dp = [0] * 366
    for i in range(1, 366):
        if i not in travel:
            dp[i] = dp[i - 1]
        else:
            dp[i] = min(
                dp[i - 1] + costs[0],
                dp[max(0, i - 7)] + costs[1],
                dp[max(0, i - 30)] + costs[2]
            )
    return dp[365]

Pro at DSA?

Test your skills with a real FAANG-style mock interview.

Start a Mock Interview →

Frequently Asked Questions

What is the Minimum Cost For Tickets problem?

Given a list of days you will travel and the costs of 1-day, 7-day, and 30-day tickets, return the minimum cost to cover all travel days. This problem uses dynamic programming where each day's cost is the minimum of buying a 1-day pass, a 7-day pass covering the last 7 days, or a 30-day pass covering the last 30 days.

How do you solve Minimum Cost For Tickets?

The optimal approach runs in O(365) time and O(365) space. Scroll up to "Optimal Approach" for the step-by-step walkthrough, diagrams, and code in Python, C++ and Java.

What companies ask Minimum Cost For Tickets?

Minimum Cost For Tickets is asked at Adobe. It is a medium difficulty problem.

What are common mistakes on Minimum Cost For Tickets?
  • Clarify the range of days (1 to 365).
  • Ask whether tickets can overlap (yes, and overlapping is allowed for minimum cost).
  • Mention that a set for travel days avoids repeated linear searches.
  • Edge cases: travel on day 1 only, all 365 days are travel days, gaps between travel days.
  • The dp transition considers max(0, i-duration) to handle boundary conditions cleanly.