{x}
blog image

Minimum Cost For Tickets

You have planned some train traveling one year in advance. The days of the year in which you will travel are given as an integer array days. Each day is an integer from 1 to 365.

Train tickets are sold in three different ways:

  • a 1-day pass is sold for costs[0] dollars,
  • a 7-day pass is sold for costs[1] dollars, and
  • a 30-day pass is sold for costs[2] dollars.

The passes allow that many days of consecutive travel.

  • For example, if we get a 7-day pass on day 2, then we can travel for 7 days: 2, 3, 4, 5, 6, 7, and 8.

Return the minimum number of dollars you need to travel every day in the given list of days.

 

Example 1:

Input: days = [1,4,6,7,8,20], costs = [2,7,15]
Output: 11
Explanation: For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 1-day pass for costs[0] = $2, which covered day 1.
On day 3, you bought a 7-day pass for costs[1] = $7, which covered days 3, 4, ..., 9.
On day 20, you bought a 1-day pass for costs[0] = $2, which covered day 20.
In total, you spent $11 and covered all the days of your travel.

Example 2:

Input: days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]
Output: 17
Explanation: For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 30-day pass for costs[2] = $15 which covered days 1, 2, ..., 30.
On day 31, you bought a 1-day pass for costs[0] = $2 which covered day 31.
In total, you spent $17 and covered all the days of your travel.

 

Constraints:

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

Minimum Cost For Tickets

This problem asks to find the minimum cost to buy train tickets to cover all travel days, given three types of tickets (1-day, 7-day, and 30-day passes) with different costs.

Approach: Dynamic Programming

The most efficient approach is dynamic programming. We create a DP array dp where dp[i] represents the minimum cost to cover travel days up to and including day i.

  1. Initialization: dp[0] = 0. There's no cost to cover zero days.

  2. Iteration: We iterate through each day i. If i is not a travel day, then dp[i] = dp[i-1] (the cost is the same as the previous day). If i is a travel day, we consider three options:

    • Buy a 1-day pass: dp[i] = dp[i-1] + costs[0]
    • Buy a 7-day pass: dp[i] = dp[max(0, i-7)] + costs[1] (we go back 7 days, or to day 0 if i < 7)
    • Buy a 30-day pass: dp[i] = dp[max(0, i-30)] + costs[2] (similarly, we go back 30 days or to day 0) We choose the minimum cost among these three options.
  3. Result: dp[last_day] contains the minimum cost to cover all travel days.

Time and Space Complexity

  • Time Complexity: O(n), where n is the number of days. We iterate through the days once.
  • Space Complexity: O(n), to store the DP array. This can be optimized to O(30) since we only need to keep track of the minimum cost for the last 30 days.

Code (Python)

def mincostTickets(days, costs):
    dp = [0] * (days[-1] + 1)  # Initialize DP array
    travel_days = set(days)    # Use a set for efficient lookup of travel days
 
    for i in range(1, days[-1] + 1):
        if i not in travel_days:
            dp[i] = dp[i - 1]  # Not a travel day, cost is the same as the previous day
            continue
 
        dp[i] = dp[i - 1] + costs[0]  # 1-day pass option
        dp[i] = min(dp[i], dp[max(0, i - 7)] + costs[1])  # 7-day pass option
        dp[i] = min(dp[i], dp[max(0, i - 30)] + costs[2]) # 30-day pass option
 
    return dp[days[-1]]
 

Code (Java)

class Solution {
    public int mincostTickets(int[] days, int[] costs) {
        int[] dp = new int[days[days.length - 1] + 1];
        boolean[] travelDays = new boolean[days[days.length - 1] + 1];
        for (int day : days) {
            travelDays[day] = true;
        }
 
        for (int i = 1; i < dp.length; i++) {
            if (!travelDays[i]) {
                dp[i] = dp[i - 1];
                continue;
            }
 
            dp[i] = dp[i - 1] + costs[0]; // 1-day pass
            dp[i] = Math.min(dp[i], dp[Math.max(0, i - 7)] + costs[1]); // 7-day pass
            dp[i] = Math.min(dp[i], dp[Math.max(0, i - 30)] + costs[2]); // 30-day pass
        }
        return dp[days[days.length - 1]];
    }
}
 

This dynamic programming solution provides an efficient way to solve the Minimum Cost For Tickets problem. The code in Python and Java demonstrates the implementation, and the complexity analysis highlights its efficiency. Other languages could follow a similar approach.