1344. Angle Between Hands of a Clock
題目 / Problem
中文: 給定兩個數字 hour(時)和 minutes(分),回傳時針與分針之間形成的較小夾角(以度為單位)。只要答案與正確值的誤差在 10⁻⁵ 以內就算正確。
English: Given two integers hour and minutes, return the smaller angle (in degrees) formed between the hour hand and the minute hand of a clock. Any answer within 10⁻⁵ of the actual value is accepted.
Constraints / 約束:
- 1 <= hour <= 12
- 0 <= minutes <= 59
Worked example / 範例: hour = 12, minutes = 30 → 輸出 165。在 12:30 時,分針指向 6(180°),時針從 12 走到了 12 與 1 之間(已走過半小時,即 15°),兩者相差 180 - 15 = 165 度。
名詞解釋 / Glossary
- 度 / degree(°):圓周分成 360 等份,每一份就是 1 度。整個鐘面是 360°。 A full circle is 360 degrees; the whole clock face spans 360°.
- 絕對值 / absolute value:一個數去掉正負號後的大小,例如
|-5| = 5。C 裡用fabs(浮點數絕對值)來計算。The magnitude of a number ignoring its sign; we usefabsfor floating-point numbers. - 取餘數 / modulo (
%):求除法剩下的餘數。13 % 12 = 1。這裡用來把 12 點當成 0 點處理。Gives the remainder of a division; used to treat 12 o'clock as 0. - 浮點數 / floating-point (
double):可以表示小數的數字型別,因為角度可能是7.5這種非整數。A number type that stores decimals, needed because angles like7.5aren't whole numbers.
思路
中文: 這題的核心是「角度」。一個完整的鐘面是 360 度,分成 12 個小時刻度,所以每小時佔 30 度(360 ÷ 12);分針則把整圈分成 60 格,所以每分鐘佔 6 度(360 ÷ 60)。
最直接的想法:分別算出分針和時針各自離 12 點的角度,再相減取絕對值。分針很簡單,minutes × 6。時針的陷阱(也是 hint 提示的地方)在於:時針不是固定停在整點,它會隨著分鐘慢慢往前移動。例如 12:30,時針已經走到 12 和 1 的中間。時針每小時走 30 度,那麼每一分鐘它額外走 30 / 60 = 0.5 度。所以時針的角度是 hour × 30 + minutes × 0.5。
要注意 hour = 12 時應當視為 0(指向正上方),用 hour % 12 處理。算出兩個角度後相減取絕對值得到 diff。但這個 diff 可能大於 180(例如算出 350 度),而題目要「較小」的夾角,這時真正的較小角是 360 - diff。所以最後回傳 min(diff, 360 - diff)。整個過程只是幾個算式,沒有迴圈,是 O(1)。
English: The whole idea is converting clock positions into degrees. A full clock is 360°. Since there are 12 hour marks, each hour is 30° (360 ÷ 12). Since there are 60 minutes around the dial, each minute is 6° (360 ÷ 60).
The straightforward plan: compute each hand's angle measured from 12, then take the absolute difference. The minute hand is easy — minutes × 6. The trap (the part the hints warn about) is the hour hand: it doesn't sit still on the hour, it creeps forward as minutes pass. At 12:30 the hour hand is halfway between 12 and 1. Since it moves 30° per hour, it moves an extra 30 / 60 = 0.5° per minute. So the hour hand's angle is hour × 30 + minutes × 0.5.
Treat hour = 12 as 0 (pointing straight up) using hour % 12. After getting both angles, subtract and take the absolute value to get diff. But diff might exceed 180° (say it comes out as 350°), and the problem wants the smaller angle — in that case the smaller side is 360 - diff. So we return min(diff, 360 - diff). It's all arithmetic, no loops, so it runs in O(1).
逐步走查 / Walkthrough
Example input / 範例輸入:hour = 12, minutes = 30
| Step / 步驟 | Computation / 計算 | Value / 數值 |
|---|---|---|
| 1. Normalize hour / 正規化時 | 12 % 12 |
0 |
| 2. Hour-hand angle / 時針角度 | 0 × 30 + 30 × 0.5 |
15.0° |
| 3. Minute-hand angle / 分針角度 | 30 × 6 |
180.0° |
| 4. Raw difference / 原始差 | fabs(180.0 - 15.0) |
165.0° |
| 5. Smaller angle / 較小夾角 | min(165.0, 360 - 165.0) = min(165.0, 195.0) |
165.0° |
時針只走了 15 度(因為過了半小時),分針指向正下方 180 度,相差 165 度,且 165 < 195,所以答案是 165。
Solution — C
// 演算法:把時針、分針各自轉成「離 12 點的角度」,相減取絕對值。
// Algorithm: convert each hand to its angle from 12 o'clock, then take the
// absolute difference. The hour hand also drifts 0.5° for every minute.
// 最後若夾角大於 180,較小角是 360 減去它 / If the gap exceeds 180°, the
// smaller angle is 360 minus it. All O(1) arithmetic.
#include <math.h> // 提供 fabs(浮點絕對值)/ provides fabs (float absolute value)
double angleClock(int hour, int minutes) {
// 時針角度:hour%12 把 12 點當成 0;每小時 30 度;每分鐘額外 0.5 度
// Hour-hand angle: hour%12 maps 12→0; 30° per hour; plus 0.5° per minute
double hourAngle = (hour % 12) * 30.0 + minutes * 0.5;
// 分針角度:每分鐘 6 度(360 度 ÷ 60 分)
// Minute-hand angle: 6° per minute (360° ÷ 60 minutes)
double minuteAngle = minutes * 6.0;
// 兩角相差,取絕對值(fabs 去掉正負號)/ absolute difference of the two angles
double diff = fabs(hourAngle - minuteAngle);
// 夾角不能超過 180;若超過就走另一邊 360-diff,取較小者
// The angle can't exceed 180°; if it does, the other side (360-diff) is smaller
return diff < 360.0 - diff ? diff : 360.0 - diff;
}
Solution — C++
// 演算法與 C 版完全相同:時針角度 = hour*30 + minutes*0.5,分針角度 = minutes*6,
// Algorithm identical to the C version: hour angle = hour*30 + minutes*0.5,
// minute angle = minutes*6, take |difference|, then the smaller of it and 360-it.
// 取兩角差的絕對值,再回傳它與 360 減它之中較小的一個。O(1)。
#include <cmath> // std::fabs / std::min 用到 / for fabs
#include <algorithm> // std::min 提供較小值 / provides std::min
class Solution {
public:
double angleClock(int hour, int minutes) {
// hour % 12 讓 12 點對齊 0 度;每小時 30 度,每分鐘再加 0.5 度
// hour % 12 aligns 12 o'clock to 0°; 30° per hour, plus 0.5° per minute
double hourAngle = (hour % 12) * 30.0 + minutes * 0.5;
// 分針:每分鐘 6 度 / minute hand: 6° per minute
double minuteAngle = minutes * 6.0;
// std::fabs 取浮點絕對值,得到兩針之間的角差
// std::fabs gives the floating-point absolute value (the raw gap)
double diff = std::fabs(hourAngle - minuteAngle);
// std::min 回傳兩者中較小的;夾角與其補角(360-diff)取小
// std::min returns the smaller of the gap and its complement (360 - gap)
return std::min(diff, 360.0 - diff);
}
};
複雜度 / Complexity
- Time: O(1) — 只是固定幾個乘法、減法和一次比較,與輸入大小無關,沒有任何迴圈。Just a fixed handful of multiplications, a subtraction, and one comparison — no loops, independent of input size.
- Space: O(1) — 只用了
hourAngle、minuteAngle、diff三個變數,不隨輸入增長。Only three scalar variables are used; nothing grows with the input.
Pitfalls & Edge Cases
- 忘記時針會移動 / Forgetting the hour hand drifts:最常見的錯誤是把時針角度寫成
hour * 30,沒加上minutes * 0.5。這樣 3:30 會算錯。The most common bug is usinghour * 30alone and dropping theminutes * 0.5term — that breaks cases like 3:30. - 12 點沒歸零 / Not wrapping 12 to 0:
hour = 12若直接乘 30 會得到 360 度而非 0 度。用hour % 12修正。Withouthour % 12, twelve o'clock becomes 360° instead of 0°. - 沒取較小夾角 / Returning the wrong side:差值可能 > 180(例如 210),題目要較小角,必須跟
360 - diff比較取小。The raw difference can exceed 180°; you must compare against360 - diffand keep the smaller. - 用整數導致小數遺失 / Integer division losing decimals:角度可能是
7.5,務必用double而非int,且寫0.5、6.0等浮點常數。Angles like7.5requiredouble; usingintwould truncate the result.