题目描述

✅ 1344. 时钟指针的夹角

image-20260929080514163

image-20260929080514353

image-20260929080514454

题意分析

给出十二小时制的小时和分钟,计算时针与分针形成的较小夹角,以度为单位返回。答案范围是零到一百八十度,可以包含小数。

指针连续运动,时针会随着本小时已经过去的分钟继续前进,不能一直停在整点刻度。小时为十二时与零时方向相同,分钟范围为零到五十九。

解法:角度计算

核心思路

[!blue]

统一以十二点方向为零度,并沿顺时针测量两根指针的位置。分针一小时转三百六十度,六十分钟平均每分钟六度,因此 minuteAngle = 6 * minutes。

时针十二小时转一圈,每小时三十度;每小时内部仍连续转动,因此每分钟再走半度。先用 hour % 12 将十二点归零,得到 hourAngle = 30 * (hour % 12) + 0.5 * minutes。

两个方向角都在同一圈内,绝对差 diff 表示沿其中一侧量出的夹角。圆周被两根指针分成两段,另一侧角度是 360 - diff,取两者较小值即可;指针重合时自然得到零,相对时得到一百八十度。

所有角度使用浮点计算,特别是时针每分钟前进的半度不能用整数除法截断。这里不需要模拟时间流逝,直接由转速和经过时间计算当前角度。

解题步骤

  1. 计算分针角度 6.0 * minutes。
  2. 计算时针角度 30.0 * (hour % 12) + 0.5 * minutes。
  3. 取两者绝对差 diff。
  4. 返回 min(diff, 360.0 - diff)。

代码实现

class Solution {
    public double angleClock(int hour, int minutes) {
        // 分针每分钟走 360 / 60 = 6 度。
        double minuteAngle = 6.0 * minutes;
        // 时针每小时走 30 度,且在一小时内以 0.5 度每分钟连续推进。
        double hourAngle = 30.0 * (hour % 12) + 0.5 * minutes;
        // 谁在前不确定,取绝对值。
        double diff = Math.abs(hourAngle - minuteAngle);

        // 两段弧之和为 360,取较小的那段。
        return Math.min(diff, 360.0 - diff);
    }
}
import "math"

func angleClock(hour int, minutes int) float64 {
    minuteAngle := 6.0 * float64(minutes)
    // 时针随分钟连续前进,每分钟另加半度。
    hourAngle := 30.0*float64(hour%12) + 0.5*float64(minutes)
    diff := math.Abs(hourAngle - minuteAngle)
    // 两个方向的夹角合为一整圈,返回较小者。
    return math.Min(diff, 360.0-diff)
}

复杂度分析

  • 时间复杂度:$O(1)$,固定次数的算术运算。
  • 空间复杂度:$O(1)$,只保存几个角度值。

关键点总结

[!green]

  • 时针每分钟前进半度,这是公式中不能漏掉的一项。
  • 取绝对值处理两指针的先后关系。
  • 返回较小方向,答案在 0° 到 180° 之间。

易错点总结

[!yellow]

  • 时针角度只计算整点部分,会漏掉分钟造成的连续偏移。
  • 用整数运算计算半度贡献,会把奇数分钟对应的小数角度截断。
  • 只返回角度绝对差,可能返回大于一百八十度的较大夹角。
  • 对一百八十取模不能代替比较两段圆弧,会把合法的一百八十度错误变成零。

相似题目

题目 难度 关联与区别
539. 最小时间差 中等 同样在周期坐标上求最短距离,不能只取绝对差,还要比较绕过周期边界的距离。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/46372050
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!