LeetCode 3687 - Library Late Fee Calculator

The problem asks us to calculate the total late fee for a library based on how many days each book was returned late. You are given an integer array daysLate, where each element daysLate[i] represents the number of days the i-th book was returned past its due date.

LeetCode Problem 3687

Difficulty: 🟢 Easy
Topics: Array, Simulation

Solution

Problem Understanding

The problem asks us to calculate the total late fee for a library based on how many days each book was returned late. You are given an integer array daysLate, where each element daysLate[i] represents the number of days the i-th book was returned past its due date. The penalty rules are tiered: if a book is late by exactly 1 day, the penalty is 1; if it is late between 2 and 5 days inclusive, the penalty is twice the number of late days; and if it is late by more than 5 days, the penalty is three times the number of late days.

The input array can have between 1 and 100 elements, and each daysLate[i] is guaranteed to be between 1 and 100. This ensures we are working with a small-scale dataset, so performance is not a major concern, but we still want a clean and correct solution. Edge cases to consider include a single book being late, all books being late by 1 day, or all books being late by more than 5 days.

The expected output is a single integer, the sum of penalties for all books.

Approaches

The brute-force approach is straightforward: iterate over each book in daysLate, compute the penalty according to the given rules, and add it to a running total. This is simple, correct, and runs efficiently given the constraints, but it involves a repeated conditional check for each element.

The optimal approach leverages the same iteration but emphasizes clear tier-based calculation without unnecessary overhead. The insight here is that the problem is already simple and bounded, so the "optimization" mainly comes from clean, readable code rather than reducing complexity.

Approach Time Complexity Space Complexity Notes
Brute Force O(n) O(1) Iterate over the array and sum penalties using conditionals
Optimal O(n) O(1) Same as brute force, but structured cleanly and clearly; no extra data structures

Algorithm Walkthrough

  1. Initialize a variable totalPenalty to zero. This will store the running sum of penalties.
  2. Loop over each element days in the daysLate array.
  3. For each days, determine the penalty using the given rules:
  • If days is exactly 1, add 1 to totalPenalty.
  • If days is between 2 and 5 inclusive, add 2 * days to totalPenalty.
  • If days is greater than 5, add 3 * days to totalPenalty.
  1. After the loop completes, return totalPenalty.

Why it works: The algorithm maintains a running sum of penalties and applies the exact rules for each book. Since each element is processed independently and correctly, the total sum at the end reflects the sum of all penalties.

Python Solution

from typing import List

class Solution:
    def lateFee(self, daysLate: List[int]) -> int:
        totalPenalty = 0
        for days in daysLate:
            if days == 1:
                totalPenalty += 1
            elif 2 <= days <= 5:
                totalPenalty += 2 * days
            else:
                totalPenalty += 3 * days
        return totalPenalty

In this implementation, totalPenalty accumulates the penalty for each book. The conditional structure clearly reflects the problem rules. Each iteration examines a single element, determines the appropriate penalty tier, and adds it to the running total.

Go Solution

func lateFee(daysLate []int) int {
    totalPenalty := 0
    for _, days := range daysLate {
        if days == 1 {
            totalPenalty += 1
        } else if days >= 2 && days <= 5 {
            totalPenalty += 2 * days
        } else {
            totalPenalty += 3 * days
        }
    }
    return totalPenalty
}

In Go, the approach is identical. The range loop iterates over each element in the slice, and the conditional checks determine the correct penalty tier. Go uses := for initialization, and integer arithmetic is straightforward since all values are small and within the 32-bit integer range.

Worked Examples

Example 1: daysLate = [5, 1, 7]

Iteration days Penalty totalPenalty
1 5 2 * 5 = 10 10
2 1 1 11
3 7 3 * 7 = 21 32

Final result: 32

Example 2: daysLate = [1, 1]

Iteration days Penalty totalPenalty
1 1 1 1
2 1 1 2

Final result: 2

Complexity Analysis

Measure Complexity Explanation
Time O(n) Each element in the array is visited exactly once
Space O(1) Only a single integer variable totalPenalty is used regardless of input size

The algorithm is efficient and uses minimal memory. Since n <= 100, performance is not a concern.

Test Cases

# Provided examples
assert Solution().lateFee([5, 1, 7]) == 32  # mixed penalties
assert Solution().lateFee([1, 1]) == 2     # all minimal penalties

# Edge cases
assert Solution().lateFee([1]) == 1        # single book, minimum late
assert Solution().lateFee([100]) == 300    # single book, large late
assert Solution().lateFee([2, 3, 4, 5]) == 28  # all mid-range penalties
assert Solution().lateFee([6, 7, 8]) == 63     # all high penalties
assert Solution().lateFee([1, 2, 5, 6, 100]) == 1 + 4 + 10 + 18 + 300  # mixed extremes
Test Why
[5,1,7] Validates all penalty tiers together
[1,1] All minimum late penalties
[1] Single-element edge case
[100] Large late days single book
[2,3,4,5] Mid-tier penalties only
[6,7,8] High-tier penalties only
[1,2,5,6,100] Mixed extremes to ensure summing works

Edge Cases

One edge case is when the array contains a single element. This tests that the function correctly handles arrays of length one and does not assume multiple elements. Another edge case is when all elements are at the boundary values for penalty tiers, such as 1, 2, 5, and 6. This ensures that the conditional logic correctly handles inequalities. A third edge case is when all books are returned very late, for instance 100 days. This tests integer arithmetic and summing, ensuring no overflow or logic errors. In all cases, our implementation directly applies the rules per element, so it handles these edge cases correctly.