Pairs of Songs With Total Durations Divisible by 60 in Python

Finding pairs of songs with total durations divisible by 60 is a common algorithmic problem. We can solve this efficiently using the remainder approach with a hash map to track remainders when dividing by 60.

Problem Understanding

Given a list of song durations, we need to count pairs where the sum is divisible by 60. For example, with [30, 20, 150, 100, 40], we get 3 pairs: (30, 150), (20, 100), and (20, 40) since 180, 120, and 60 are all divisible by 60.

Algorithm Approach

The key insight is using modular arithmetic:

  • Two numbers sum to a multiple of 60 if their remainders add to 60 (or both are 0)
  • Track remainder frequencies in a hash map
  • For each song, check if its complement remainder exists
  • Special case: songs with 0 remainder (divisible by 60) pair with each other

Solution Implementation

def numPairsDivisibleBy60(time):
    ans = 0
    remainder = {}
    
    for duration in time:
        current_remainder = duration % 60
        
        if current_remainder == 0 and 0 in remainder:
            # Songs divisible by 60 pair with other songs divisible by 60
            ans += remainder[0]
        elif (60 - current_remainder) in remainder:
            # Find complement remainder
            ans += remainder[60 - current_remainder]
        
        # Update remainder frequency
        if current_remainder in remainder:
            remainder[current_remainder] += 1
        else:
            remainder[current_remainder] = 1
    
    return ans

# Test the function
time_list = [30, 20, 150, 100, 40]
result = numPairsDivisibleBy60(time_list)
print(f"Number of pairs: {result}")

# Show the actual pairs for verification
print("\nPairs found:")
for i in range(len(time_list)):
    for j in range(i + 1, len(time_list)):
        if (time_list[i] + time_list[j]) % 60 == 0:
            print(f"({time_list[i]}, {time_list[j]}) = {time_list[i] + time_list[j]}")
Number of pairs: 3

Pairs found:
(30, 150) = 180
(20, 100) = 120
(20, 40) = 60

How It Works

The algorithm works by tracking remainder frequencies:

  1. Remainder 30: Needs remainder 30 to sum to 60
  2. Remainder 20: Needs remainder 40 to sum to 60
  3. Remainder 0: Pairs with other remainder 0 values

Optimized Version

Here's a cleaner implementation using Python's defaultdict ?

from collections import defaultdict

def numPairsDivisibleBy60Optimized(time):
    remainder_count = defaultdict(int)
    pairs = 0
    
    for duration in time:
        remainder = duration % 60
        complement = (60 - remainder) % 60
        
        pairs += remainder_count[complement]
        remainder_count[remainder] += 1
    
    return pairs

# Test with the same example
time_list = [30, 20, 150, 100, 40]
result = numPairsDivisibleBy60Optimized(time_list)
print(f"Number of pairs (optimized): {result}")
Number of pairs (optimized): 3

Time and Space Complexity

Aspect Complexity Explanation
Time O(n) Single pass through the array
Space O(1) At most 60 different remainders

Conclusion

This problem efficiently demonstrates using modular arithmetic and hash maps for counting pairs. The key insight is that two numbers sum to a multiple of 60 when their remainders complement each other to 60.

Updated on: 2026-03-25T07:20:32+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements