questions A (01-matrix - avoid-flood)
This commit is contained in:
155
backend/data/questions/angle-between-hands-of-a-clock.yaml
Normal file
155
backend/data/questions/angle-between-hands-of-a-clock.yaml
Normal file
@@ -0,0 +1,155 @@
|
||||
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`
|
||||
|
||||
|
||||
|
||||
**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
|
||||
|
||||
|
||||
|
||||
**Step 3: Calculate the absolute difference**
|
||||
|
||||
- Difference: `abs(hour_angle - minute_angle)`
|
||||
|
||||
|
||||
|
||||
**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.
|
||||
Reference in New Issue
Block a user