Bird
Raised Fist0
Interview Prepmath-geometrymediumAmazonGoogleFacebook

Angle Between Hands of a Clock

Choose your preparation mode4 modes available
🎯
Angle Between Hands of a Clock
mediumMATHAmazonGoogleFacebook

Imagine you want to build a smart clock app that shows the exact angle between the hour and minute hands at any given time.

💡 This problem involves understanding how clock hands move continuously and calculating angles accordingly. Beginners often struggle because the hour hand moves as the minutes pass, so it's not enough to just look at the hour and minute separately.
📋
Problem Statement

Given two integers hour and minutes, return the smaller angle (in degrees) formed between the hour and the minute hand on a clock.

1 ≤ hour ≤ 120 ≤ minutes ≤ 59
💡
Example
Input"hour = 3, minutes = 30"
Output75

At 3:30, the hour hand is halfway between 3 and 4 (3 * 30 + 30 * 0.5 = 105 degrees), the minute hand is at 180 degrees, so the angle between them is 75 degrees.

Input"hour = 12, minutes = 0"
Output0

At 12:00, both hands point at 12, so the angle is 0 degrees.

  • hour = 12, minutes = 59 → angle close to 5.5 degrees
  • hour = 1, minutes = 0 → angle is 30 degrees
  • hour = 6, minutes = 0 → angle is 180 degrees
  • hour = 11, minutes = 59 → angle close to 5.5 degrees
⚠️
Common Mistakes
Ignoring that the hour hand moves as minutes pass

Incorrect angle calculation, especially at times like 3:30

✅ Add minutes * 0.5 degrees to hour hand angle

Not normalizing hour to 12-hour format

Incorrect angle for hours > 12, e.g., 15:00

✅ Use hour % 12 before calculations

Returning the absolute difference without taking the smaller angle

Angles greater than 180 degrees returned, which is incorrect

✅ Return min(diff, 360 - diff)

Using integer division instead of floating-point for angles

Loss of precision, wrong answers for times like 3:30

✅ Use floating-point arithmetic for minute contributions

Not handling edge cases like 12:00 or 0 minutes

Unexpected results or errors

✅ Test and handle these explicitly or rely on modulo normalization

🧠
Brute Force (Direct Angle Calculation)
💡 Starting with a straightforward calculation helps understand how the hour and minute hands move and how to compute their angles without optimizations.

Intuition

Calculate the angle of the hour hand and the minute hand separately, then find the absolute difference. Since the clock is circular, the smaller angle is the minimum between this difference and 360 minus this difference.

Algorithm

  1. Calculate the hour hand angle: hour * 30 + minutes * 0.5 degrees.
  2. Calculate the minute hand angle: minutes * 6 degrees.
  3. Find the absolute difference between the two angles.
  4. Return the minimum of the difference and 360 minus the difference.
💡 The key difficulty is remembering that the hour hand moves as minutes pass, and the angle difference must be normalized to the smaller angle.
</>
Code
def angleClock(hour: int, minutes: int) -> float:
    hour_angle = (hour % 12) * 30 + minutes * 0.5
    minute_angle = minutes * 6
    diff = abs(hour_angle - minute_angle)
    return min(diff, 360 - diff)

# Driver code
if __name__ == '__main__':
    print(angleClock(3, 30))  # Expected: 75
    print(angleClock(12, 0))  # Expected: 0
Line Notes
hour_angle = (hour % 12) * 30 + minutes * 0.5Normalize hour to 12-hour format and calculate hour hand angle including minute contribution
minute_angle = minutes * 6Calculate minute hand angle; each minute is 6 degrees
diff = abs(hour_angle - minute_angle)Find absolute difference between the two angles
return min(diff, 360 - diff)Return the smaller angle between the two possible arcs
public class Solution {
    public static double angleClock(int hour, int minutes) {
        double hourAngle = (hour % 12) * 30 + minutes * 0.5;
        double minuteAngle = minutes * 6;
        double diff = Math.abs(hourAngle - minuteAngle);
        return Math.min(diff, 360 - diff);
    }

    public static void main(String[] args) {
        System.out.println(angleClock(3, 30)); // Expected: 75
        System.out.println(angleClock(12, 0)); // Expected: 0
    }
}
Line Notes
double hourAngle = (hour % 12) * 30 + minutes * 0.5;Normalize hour and calculate hour hand angle including minute offset
double minuteAngle = minutes * 6;Calculate minute hand angle
double diff = Math.abs(hourAngle - minuteAngle);Compute absolute difference between angles
return Math.min(diff, 360 - diff);Return smaller angle between two arcs
#include <iostream>
#include <cmath>
using namespace std;

double angleClock(int hour, int minutes) {
    double hourAngle = (hour % 12) * 30 + minutes * 0.5;
    double minuteAngle = minutes * 6;
    double diff = fabs(hourAngle - minuteAngle);
    return min(diff, 360 - diff);
}

int main() {
    cout << angleClock(3, 30) << endl; // Expected: 75
    cout << angleClock(12, 0) << endl; // Expected: 0
    return 0;
}
Line Notes
double hourAngle = (hour % 12) * 30 + minutes * 0.5;Normalize hour and calculate hour hand angle with minute contribution
double minuteAngle = minutes * 6;Calculate minute hand angle
double diff = fabs(hourAngle - minuteAngle);Calculate absolute difference between angles
return min(diff, 360 - diff);Return smaller angle between two possible arcs
function angleClock(hour, minutes) {
    const hourAngle = (hour % 12) * 30 + minutes * 0.5;
    const minuteAngle = minutes * 6;
    const diff = Math.abs(hourAngle - minuteAngle);
    return Math.min(diff, 360 - diff);
}

// Test cases
console.log(angleClock(3, 30)); // Expected: 75
console.log(angleClock(12, 0)); // Expected: 0
Line Notes
const hourAngle = (hour % 12) * 30 + minutes * 0.5;Normalize hour and calculate hour hand angle including minute offset
const minuteAngle = minutes * 6;Calculate minute hand angle
const diff = Math.abs(hourAngle - minuteAngle);Find absolute difference between angles
return Math.min(diff, 360 - diff);Return smaller angle between two arcs
⏱
Complexity
TimeO(1)
SpaceO(1)

All calculations are constant time arithmetic operations, no loops or recursion.

💡 This means the solution runs instantly regardless of input size, as the problem size is fixed.
Interview Verdict: Accepted

This approach is efficient and accepted because it directly computes the answer with constant time and space.

🧠
Using Modular Arithmetic and Angle Normalization
💡 This approach emphasizes modular arithmetic to handle hour normalization and uses a helper function to normalize angles, improving code clarity and robustness.

Intuition

Normalize the hour to 12-hour format using modulo, calculate angles, then normalize the difference to always get the smaller angle by wrapping around 360 degrees.

Algorithm

  1. Normalize hour using modulo 12.
  2. Calculate hour and minute hand angles.
  3. Calculate absolute difference.
  4. Normalize difference to be ≤ 180 degrees by subtracting from 360 if needed.
💡 This approach makes the angle normalization explicit, which helps avoid mistakes with angles greater than 180 degrees.
</>
Code
def normalize_angle(angle):
    angle %= 360
    return angle if angle <= 180 else 360 - angle

def angleClock(hour: int, minutes: int) -> float:
    hour = hour % 12
    hour_angle = hour * 30 + minutes * 0.5
    minute_angle = minutes * 6
    diff = abs(hour_angle - minute_angle)
    return normalize_angle(diff)

# Driver code
if __name__ == '__main__':
    print(angleClock(3, 30))  # Expected: 75
    print(angleClock(12, 0))  # Expected: 0
Line Notes
angle %= 360Ensure angle stays within 0 to 359 degrees
return angle if angle <= 180 else 360 - angleReturn smaller angle by normalizing to ≤ 180 degrees
hour = hour % 12Normalize hour to 12-hour format
diff = abs(hour_angle - minute_angle)Calculate absolute difference between angles
public class Solution {
    private static double normalizeAngle(double angle) {
        angle %= 360;
        return angle <= 180 ? angle : 360 - angle;
    }

    public static double angleClock(int hour, int minutes) {
        hour %= 12;
        double hourAngle = hour * 30 + minutes * 0.5;
        double minuteAngle = minutes * 6;
        double diff = Math.abs(hourAngle - minuteAngle);
        return normalizeAngle(diff);
    }

    public static void main(String[] args) {
        System.out.println(angleClock(3, 30)); // Expected: 75
        System.out.println(angleClock(12, 0)); // Expected: 0
    }
}
Line Notes
angle %= 360;Keep angle within 0 to 359 degrees
return angle <= 180 ? angle : 360 - angle;Return smaller angle by normalizing
hour %= 12;Normalize hour to 12-hour format
double diff = Math.abs(hourAngle - minuteAngle);Calculate absolute difference between angles
#include <iostream>
#include <cmath>
using namespace std;

double normalizeAngle(double angle) {
    angle = fmod(angle, 360);
    return angle <= 180 ? angle : 360 - angle;
}

double angleClock(int hour, int minutes) {
    hour = hour % 12;
    double hourAngle = hour * 30 + minutes * 0.5;
    double minuteAngle = minutes * 6;
    double diff = fabs(hourAngle - minuteAngle);
    return normalizeAngle(diff);
}

int main() {
    cout << angleClock(3, 30) << endl; // Expected: 75
    cout << angleClock(12, 0) << endl; // Expected: 0
    return 0;
}
Line Notes
angle = fmod(angle, 360);Keep angle within 0 to 359 degrees using floating-point modulo
return angle <= 180 ? angle : 360 - angle;Return smaller angle by normalization
hour = hour % 12;Normalize hour to 12-hour format
double diff = fabs(hourAngle - minuteAngle);Calculate absolute difference between angles
function normalizeAngle(angle) {
    angle = angle % 360;
    return angle <= 180 ? angle : 360 - angle;
}

function angleClock(hour, minutes) {
    hour = hour % 12;
    const hourAngle = hour * 30 + minutes * 0.5;
    const minuteAngle = minutes * 6;
    const diff = Math.abs(hourAngle - minuteAngle);
    return normalizeAngle(diff);
}

// Test cases
console.log(angleClock(3, 30)); // Expected: 75
console.log(angleClock(12, 0)); // Expected: 0
Line Notes
angle = angle % 360;Normalize angle within 0 to 359 degrees
return angle <= 180 ? angle : 360 - angle;Return smaller angle by normalization
hour = hour % 12;Normalize hour to 12-hour format
const diff = Math.abs(hourAngle - minuteAngle);Calculate absolute difference between angles
⏱
Complexity
TimeO(1)
SpaceO(1)

All operations are constant time arithmetic and modulo operations.

💡 This approach is just as fast as the brute force but improves clarity and correctness by explicitly normalizing angles.
Interview Verdict: Accepted

This approach is preferred for clarity and robustness in interviews.

🧠
Precompute Angles and Use Lookup (Optimization for Multiple Queries)
💡 If the problem requires multiple queries, precomputing angles for all possible times can speed up repeated calculations.

Intuition

Since the clock has only 12 hours and 60 minutes, precompute the angle for every possible time and answer queries in O(1) by lookup.

Algorithm

  1. Create a 12x60 2D array to store angles for each hour and minute.
  2. For each hour and minute, compute the angle using the formula from approach 1.
  3. For each query, return the precomputed angle from the array.
💡 This trades space for time, useful when many queries are expected.
</>
Code
class ClockAngle:
    def __init__(self):
        self.precomputed = [[0]*60 for _ in range(12)]
        for h in range(12):
            for m in range(60):
                hour_angle = h * 30 + m * 0.5
                minute_angle = m * 6
                diff = abs(hour_angle - minute_angle)
                self.precomputed[h][m] = min(diff, 360 - diff)

    def angleClock(self, hour: int, minutes: int) -> float:
        return self.precomputed[hour % 12][minutes]

# Driver code
if __name__ == '__main__':
    clock = ClockAngle()
    print(clock.angleClock(3, 30))  # Expected: 75
    print(clock.angleClock(12, 0))  # Expected: 0
Line Notes
self.precomputed = [[0]*60 for _ in range(12)]Initialize 12x60 matrix to store angles for all times
for h in range(12):Iterate over all hours in 12-hour format
self.precomputed[h][m] = min(diff, 360 - diff)Store the smaller angle for each time
return self.precomputed[hour % 12][minutes]Return precomputed angle for given time
public class ClockAngle {
    private double[][] precomputed = new double[12][60];

    public ClockAngle() {
        for (int h = 0; h < 12; h++) {
            for (int m = 0; m < 60; m++) {
                double hourAngle = h * 30 + m * 0.5;
                double minuteAngle = m * 6;
                double diff = Math.abs(hourAngle - minuteAngle);
                precomputed[h][m] = Math.min(diff, 360 - diff);
            }
        }
    }

    public double angleClock(int hour, int minutes) {
        return precomputed[hour % 12][minutes];
    }

    public static void main(String[] args) {
        ClockAngle clock = new ClockAngle();
        System.out.println(clock.angleClock(3, 30)); // Expected: 75
        System.out.println(clock.angleClock(12, 0)); // Expected: 0
    }
}
Line Notes
private double[][] precomputed = new double[12][60];Create 2D array to store angles for all times
for (int h = 0; h < 12; h++) {Iterate over all hours
precomputed[h][m] = Math.min(diff, 360 - diff);Store smaller angle for each hour and minute
return precomputed[hour % 12][minutes];Return precomputed angle for query
#include <iostream>
#include <cmath>
using namespace std;

double precomputed[12][60];

void precompute() {
    for (int h = 0; h < 12; h++) {
        for (int m = 0; m < 60; m++) {
            double hourAngle = h * 30 + m * 0.5;
            double minuteAngle = m * 6;
            double diff = fabs(hourAngle - minuteAngle);
            precomputed[h][m] = min(diff, 360 - diff);
        }
    }
}

double angleClock(int hour, int minutes) {
    return precomputed[hour % 12][minutes];
}

int main() {
    precompute();
    cout << angleClock(3, 30) << endl; // Expected: 75
    cout << angleClock(12, 0) << endl; // Expected: 0
    return 0;
}
Line Notes
double precomputed[12][60];Global 2D array to store angles for all times
for (int h = 0; h < 12; h++) {Iterate over all hours
precomputed[h][m] = min(diff, 360 - diff);Store smaller angle for each time
return precomputed[hour % 12][minutes];Return precomputed angle for given query
class ClockAngle {
    constructor() {
        this.precomputed = Array.from({ length: 12 }, () => Array(60).fill(0));
        for (let h = 0; h < 12; h++) {
            for (let m = 0; m < 60; m++) {
                const hourAngle = h * 30 + m * 0.5;
                const minuteAngle = m * 6;
                const diff = Math.abs(hourAngle - minuteAngle);
                this.precomputed[h][m] = Math.min(diff, 360 - diff);
            }
        }
    }

    angleClock(hour, minutes) {
        return this.precomputed[hour % 12][minutes];
    }
}

// Test cases
const clock = new ClockAngle();
console.log(clock.angleClock(3, 30)); // Expected: 75
console.log(clock.angleClock(12, 0)); // Expected: 0
Line Notes
this.precomputed = Array.from({ length: 12 }, () => Array(60).fill(0));Initialize 12x60 matrix for precomputed angles
for (let h = 0; h < 12; h++) {Iterate over all hours
this.precomputed[h][m] = Math.min(diff, 360 - diff);Store smaller angle for each time
return this.precomputed[hour % 12][minutes];Return precomputed angle for query
⏱
Complexity
TimeO(1) per query after O(720) precomputation
SpaceO(720) for precomputed table

Precomputation takes constant time since 12*60=720 is fixed; queries are answered in constant time.

💡 This approach is useful when many queries are expected, trading a small fixed memory for instant answers.
Interview Verdict: Accepted

This approach is optimal for multiple queries but unnecessary for single queries.

📊
All Approaches - One-Glance Tradeoffs
💡 In most interviews, approach 1 or 2 is sufficient and preferred for clarity and speed.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute Force (Direct Calculation)O(1)O(1)NoN/ACode this approach first; it's simple and efficient.
2. Modular Arithmetic and NormalizationO(1)O(1)NoN/APreferred for clarity and correctness; mention if asked about angle normalization.
3. Precompute Angles for Multiple QueriesO(1) per query after O(720) precomputeO(720)NoN/AMention if multiple queries expected; rarely code fully unless asked.
💼
Interview Strategy
💡 Use this guide to understand the problem deeply, practice coding all approaches, and prepare to explain your reasoning clearly in interviews.

How to Present

Step 1: Clarify input constraints and ask if multiple queries are expected.Step 2: Explain the brute force approach calculating angles directly.Step 3: Discuss angle normalization and modular arithmetic for clarity.Step 4: If multiple queries, mention precomputation optimization.Step 5: Code the chosen approach and test with edge cases.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 8min → Test: 2min. Total ~15min

What the Interviewer Tests

Interviewer tests your understanding of continuous movement of the hour hand, angle normalization, and ability to handle edge cases like 12:00 or 11:59.

Common Follow-ups

  • What if the clock is 24-hour format? → Normalize hour modulo 12.
  • How to handle seconds? → Include seconds in hour and minute angle calculations.
  • What if you want the larger angle? → Return max(diff, 360 - diff).
  • How to handle invalid inputs? → Validate hour and minutes before calculation.
💡 These follow-ups test your ability to extend the solution and handle real-world variations.
🔍
Pattern Recognition

When to Use

1) Problem involves clock hands or circular angles, 2) Need smaller angle between two pointers, 3) Continuous movement of hour hand matters, 4) Normalize angles within 360 degrees.

Signature Phrases

angle between hour and minute handsmaller angle on a clock

NOT This Pattern When

Problems involving discrete steps or only minute hand movement without continuous hour hand movement.

Similar Problems

Minimum Angle Between Clock Hands - similar angle calculationClock Angle Problem Variations - extensions with seconds or 24-hour format

Practice

(1/5)
1. You are given a list of points on a 2D plane. Your task is to find the rectangle with the minimum area such that all four corners are points from the list. Which approach guarantees finding the optimal solution efficiently?
easy
A. Use a hash set to store points and check pairs of points as diagonals to find rectangles.
B. Use dynamic programming to build rectangles from smaller sub-rectangles.
C. Use a greedy approach by sorting points and selecting closest pairs to form rectangles.
D. Use a brute force approach checking all quadruples of points to find rectangles.

Solution

  1. Step 1: Understand the problem constraints

    The problem requires finding rectangles formed by points with minimum area, which involves checking pairs of points as potential diagonals.
  2. Step 2: Evaluate approaches

    Brute force (checking all quadruples) is correct but inefficient (O(n^4)). Greedy and DP approaches do not guarantee correctness or efficiency here. Using a hash set to check existence of complementary points for diagonals is both correct and efficient (O(n^2)).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Hash set + diagonal pairs -> optimal and correct [OK]
Hint: Hash set + diagonal pairs is key [OK]
Common Mistakes:
  • Thinking greedy or DP solves this efficiently
  • Using brute force without pruning
2. Consider the following code snippet that checks if a number is a palindrome by reversing half of its digits. What is the value of reversed_half after the second iteration of the while loop when input is 12321?
easy
A. 12
B. 1
C. 21
D. 123

Solution

  1. Step 1: Trace first iteration

    Initial x=12321, reversed_half=0 reversed_half = 0*10 + 12321%10 = 1 x = 12321 // 10 = 1232
  2. Step 2: Trace second iteration

    reversed_half = 1*10 + 1232%10 = 10 + 2 = 12 x = 1232 // 10 = 123
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    After two iterations reversed_half is 12 [OK]
Hint: Track variable updates carefully each loop iteration [OK]
Common Mistakes:
  • Off-by-one iteration count
  • Mixing x and reversed_half values
  • Incorrect modulo or division
3. Given the following Python code to find the nth ugly number, what is the output when calling nthUglyNumber(4)?
import heapq

def nthUglyNumber(n):
    heap = [1]
    seen = {1}
    ugly = 1
    for _ in range(n):
        ugly = heapq.heappop(heap)
        for factor in [2, 3, 5]:
            new_ugly = ugly * factor
            if new_ugly not in seen:
                seen.add(new_ugly)
                heapq.heappush(heap, new_ugly)
    return ugly

print(nthUglyNumber(4))
easy
A. 6
B. 5
C. 8
D. 4

Solution

  1. Step 1: Trace heap pops and pushes for n=4

    Initial heap: [1]. Iteration 1 pops 1, pushes 2,3,5. Iteration 2 pops 2, pushes 4,6,10. Iteration 3 pops 3, pushes 6 (already seen), 9, 15. Iteration 4 pops 4, pushes 8,12,20.
  2. Step 2: Identify the 4th popped ugly number

    The popped numbers in order are 1, 2, 3, 4. The 4th ugly number is 4, so nthUglyNumber(4) returns 4.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    4 is the 4th ugly number generated by the heap [OK]
Hint: Heap pops nth ugly number in ascending order [OK]
Common Mistakes:
  • Confusing the iteration count with the returned value
  • Forgetting duplicates are skipped
  • Miscounting the order of popped elements
4. The following code attempts to count primes less than n using an optimized sieve. Identify the line containing the subtle bug that causes incorrect results or inefficiency.
def countPrimes(n):
    if n <= 2:
        return 0
    is_prime = [True] * (n // 2)
    is_prime[0] = False  # 1 is not prime
    for i in range(3, int(n**0.5) + 1, 2):
        if is_prime[i // 2]:
            for j in range(i, n, 2 * i):  # Bug here
                is_prime[j // 2] = False
    return 1 + sum(is_prime)  # add prime 2
medium
A. Line setting is_prime[0] = false
B. Line returning 1 + sum(is_prime)
C. Line starting the inner loop from j = i instead of i * i
D. Line checking if n <= 2 and returning 0

Solution

  1. Step 1: Understand inner loop start

    The inner loop should start marking multiples from i*i, not i, to avoid redundant marking.
  2. Step 2: Identify impact of bug

    Starting from i causes marking the prime number i itself as non-prime, corrupting results.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Correct sieve starts marking from i*i to preserve prime i [OK]
Hint: Mark multiples from i*i to avoid marking primes themselves [OK]
Common Mistakes:
  • Starting marking from i instead of i*i
  • Mislabeling 1 as prime
  • Forgetting to add prime 2
5. Suppose rectangles can have zero area (width or height zero) and you want to consider touching edges as overlapping. Which modification to the optimal overlap check code correctly implements this?
hard
A. Add a separate check for zero-area rectangles and return true if their edges touch.
B. Ignore zero-area rectangles entirely since they cannot overlap.
C. Use a brute force grid scan to check all points inside the rectangles for overlap.
D. Change the return condition to 'x_overlap >= 0 and y_overlap >= 0' to include touching edges.

Solution

  1. Step 1: Understand the new overlap definition

    Touching edges count as overlap, so zero-length overlaps on axes are valid.
  2. Step 2: Modify the condition to include zero overlap

    Changing '> 0' to '>= 0' in the return condition correctly includes touching edges.
  3. Step 3: Confirm no extra checks needed

    Zero-area rectangles are handled naturally by this condition without extra code.
  4. Final Answer:

    Option D -> Option D
  5. Quick Check:

    Using '>=' includes edge-touching cases as overlap [OK]
Hint: Use '>=' to include touching edges as overlap [OK]
Common Mistakes:
  • Adding unnecessary complexity for zero-area rectangles
  • Ignoring zero-area rectangles leading to incorrect results
  • Using brute force which is inefficient
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard