Files
codetutor/backend/data/questions/angle-between-hands-of-a-clock.yaml

156 lines
7.2 KiB
YAML

title: Angle Between Hands of a Clock
slug: angle-between-hands-of-a-clock
difficulty: medium
leetcode_id: 1344
leetcode_url: https://leetcode.com/problems/angle-between-hands-of-a-clock/
categories:
- math
patterns:
- greedy
description: |
Given two numbers, `hour` and `minutes`, return *the smaller angle (in degrees) formed between the hour and the minute hand*.
Answers within `10^-5` of the actual value will be accepted as correct.
constraints: |
- `1 <= hour <= 12`
- `0 <= minutes <= 59`
examples:
- input: "hour = 12, minutes = 30"
output: "165"
explanation: "At 12:30, the minute hand points at 6 (180°) and the hour hand has moved halfway between 12 and 1 (15°). The angle between them is |180 - 15| = 165°."
- input: "hour = 3, minutes = 30"
output: "75"
explanation: "At 3:30, the minute hand points at 6 (180°) and the hour hand is halfway between 3 and 4 (105°). The angle between them is |180 - 105| = 75°."
- input: "hour = 3, minutes = 15"
output: "7.5"
explanation: "At 3:15, the minute hand points at 3 (90°) and the hour hand has moved slightly past 3 (97.5°). The angle between them is |97.5 - 90| = 7.5°."
explanation:
intuition: |
Picture an analog clock face as a circle divided into 360 degrees. The key insight is that **both hands move independently at constant rates**, and we can calculate exactly where each hand points at any given time.
Think of it like this: the clock face is a coordinate system where 12 o'clock is 0° (or 360°), and angles increase clockwise. Each hand sweeps around this circle at a different speed:
- The **minute hand** completes a full rotation (360°) in 60 minutes, so it moves **6° per minute**
- The **hour hand** completes a full rotation in 12 hours (720 minutes), so it moves **0.5° per minute**
The crucial detail many miss is that the **hour hand moves continuously**, not just jumping from hour to hour. At 3:30, the hour hand isn't pointing exactly at 3 — it's halfway between 3 and 4 because half an hour has passed.
Once we know where each hand points, we calculate the absolute difference. But since we want the *smaller* angle (a clock has two angles between any two hands), we take the minimum of the angle and `360 - angle`.
approach: |
We solve this using **direct angle calculation**:
**Step 1: Calculate the minute hand's position**
- The minute hand moves 360° in 60 minutes
- Rate: `360 / 60 = 6°` per minute
- Position: `minutes * 6`
&nbsp;
**Step 2: Calculate the hour hand's position**
- The hour hand moves 360° in 12 hours
- Rate: `360 / 12 = 30°` per hour
- But it also moves as minutes pass: `30 / 60 = 0.5°` per minute
- Position: `(hour % 12) * 30 + minutes * 0.5`
- Note: We use `hour % 12` because hour 12 should be treated as 0
&nbsp;
**Step 3: Calculate the absolute difference**
- Difference: `abs(hour_angle - minute_angle)`
&nbsp;
**Step 4: Return the smaller angle**
- A clock face has two angles between any two points (they sum to 360°)
- Return `min(angle, 360 - angle)` to get the smaller one
common_pitfalls:
- title: Forgetting the Hour Hand Moves Continuously
description: |
A common mistake is treating the hour hand as if it only points to exact hour positions. At 3:30, the hour hand is NOT at the 3 — it's halfway between 3 and 4.
The hour hand moves 0.5° per minute (30° per hour ÷ 60 minutes). So at 3:30, it's at `3 * 30 + 30 * 0.5 = 90 + 15 = 105°`, not 90°.
wrong_approach: "hour_angle = hour * 30"
correct_approach: "hour_angle = (hour % 12) * 30 + minutes * 0.5"
- title: Not Handling Hour 12
description: |
When `hour = 12`, the hour hand is at the 12 o'clock position (0°), not at 360°. If you don't use modulo, you'll calculate `12 * 30 = 360°`, which is technically correct but can cause issues when computing the smaller angle.
Using `hour % 12` normalises hour 12 to 0, giving the correct position of 0°.
wrong_approach: "hour * 30"
correct_approach: "(hour % 12) * 30"
- title: Returning the Larger Angle
description: |
Two clock hands create two angles that sum to 360°. The problem asks for the *smaller* angle.
For example, if the hands are 270° apart, the smaller angle is `360 - 270 = 90°`. Always return `min(angle, 360 - angle)`.
wrong_approach: "Return abs(hour_angle - minute_angle)"
correct_approach: "Return min(angle, 360 - angle)"
key_takeaways:
- "**Rate-based thinking**: Convert cyclic movements to angular velocities (degrees per unit time) for precise calculations"
- "**Continuous vs discrete**: Physical quantities like clock hands move continuously — don't discretise them unless necessary"
- "**Circular geometry**: When dealing with circular positions, remember there are always two ways to measure between any two points"
- "**Modular arithmetic**: Use modulo to handle wraparound cases cleanly (12 o'clock → 0)"
time_complexity: "O(1). We perform a fixed number of arithmetic operations regardless of input values."
space_complexity: "O(1). We only use a constant number of variables to store the angles."
solutions:
- approach_name: Direct Angle Calculation
is_optimal: true
code: |
def angle_clock(hour: int, minutes: int) -> float:
# Minute hand: 360° / 60 min = 6° per minute
minute_angle = minutes * 6
# Hour hand: 30° per hour + 0.5° per minute
# Use hour % 12 so that 12 o'clock is treated as 0°
hour_angle = (hour % 12) * 30 + minutes * 0.5
# Calculate the absolute difference between hands
diff = abs(hour_angle - minute_angle)
# Return the smaller of the two possible angles
return min(diff, 360 - diff)
explanation: |
**Time Complexity:** O(1) — Only basic arithmetic operations.
**Space Complexity:** O(1) — Only a few variables used.
We calculate each hand's position using their angular velocities, find the absolute difference, and return the smaller of the two possible angles. The key insight is that the hour hand moves continuously, advancing 0.5° for each minute that passes.
- approach_name: Separate Rate Constants
is_optimal: false
code: |
def angle_clock(hour: int, minutes: int) -> float:
# Define angular velocities as constants
MINUTE_HAND_RATE = 6.0 # degrees per minute
HOUR_HAND_RATE = 0.5 # degrees per minute
HOUR_MARK_ANGLE = 30.0 # degrees between hour marks
# Calculate positions
minute_pos = minutes * MINUTE_HAND_RATE
hour_pos = (hour % 12) * HOUR_MARK_ANGLE + minutes * HOUR_HAND_RATE
# Get smaller angle
angle = abs(minute_pos - hour_pos)
return min(angle, 360 - angle)
explanation: |
**Time Complexity:** O(1) — Same operations as optimal solution.
**Space Complexity:** O(1) — Uses named constants for clarity.
This approach uses named constants to make the angular velocities explicit. While functionally identical to the optimal solution, the named constants (`MINUTE_HAND_RATE`, `HOUR_HAND_RATE`) make the code more self-documenting and easier to understand.