LeetCode 1185 Day of the Week 题解用 Go 标准库 time 与多种星期算法计算星期几【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go本篇指南以 LeetCode 第 1185 题《Day of the Week》为核心结合当前仓库 LeetCode-Go 中该题的实际实现讲解如何根据输入的日、月、年判断对应星期。读完本文你将掌握基于 Go 标准库time的极简解法理解time.Date与Weekday的底层行为并了解 Zeller蔡勒公式、Sakamoto 算法等经典星期计算原理以及本仓库配套测试的验证方式。题目回顾Given a date, return the corresponding day of the week for that date.The input is given as three integers representing theday,monthandyearrespectively.Return the answer as one of the following values{Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}.翻译过来即给你一个日期请你设计一个算法来判断它是对应一周中的哪一天。输入为三个整数day、month和year分别表示日、月、年返回的结果必须是以下七个值之一{Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}示例输入 (day, month, year)输出31, 8, 2019Saturday18, 7, 1999Sunday15, 8, 1993Sunday约束条件给出的日期一定是1971到2100年之间的有效日期。这意味着题目保证输入合法我们无需自行校验日期的正确性也无需处理 1971 年之前的复杂历法规则如儒略历与格里高利历的切换大幅简化了实现难度。解题思路概览题目本身是一道简单题属于按照常识计算即可的范畴。但算星期几这个看似简单的问题在实现层面却有多种路线差别主要体现在是否依赖标准库Go 的time包已经内置了完整的日期计算能力一行即可求解本仓库采用此方案是否依赖记忆公式如蔡勒公式Zellers congruence、Sakamoto 算法等不依赖标准库适合无库环境或面试手写是否依赖基准日累加选定一个已知星期的日期作为锚点逐日累加偏移量。下面先给出本仓库的官方实现再逐一展开各类算法原理。仓库源码解析基于 Go 标准库time的极简实现当前仓库 LeetCode-Go 中1185.Day-of-the-Week 题解源码 的完整实现如下package leetcode import time func dayOfTheWeek(day int, month int, year int) string { return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local).Weekday().String() }整个函数只有一行核心逻辑其执行链路可以拆解为三个阶段第一步time.Date构造时间点time.Date(year, month, day, hour, min, sec, nsec, loc)是 Go 标准库中用于构造time.Time的函数参数依次为年、月、日、时、分、秒、纳秒和时区。time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)这里有两个值得注意的细节类型转换month是题目传入的int类型而time.Date的第二个参数要求time.Month类型。time.Month本质上是int的别名类型因此通过time.Month(month)显式转换即可时区选择源码使用了time.Local本地时区。由于星期几只与公历日期相关与具体时区无关因此这里无论传入本地时区还是time.UTC计算结果都一致。另外time.Date具有日期规范化normalization能力例如月份 0 会被解析为上一年 12 月、第 0 天会被解析为上个月最后一天。虽然本题输入保证是有效日期、用不到这一特性但了解这一点有助于理解time包内部的日期处理机制。第二步Weekday()获取星期枚举time.Time.Weekday()返回一个time.Weekday类型的枚举值其取值范围与对应关系为枚举值数值字符串表示time.Sunday0Sundaytime.Monday1Mondaytime.Tuesday2Tuesdaytime.Wednesday3Wednesdaytime.Thursday4Thursdaytime.Friday5Fridaytime.Saturday6Saturday第三步String()映射为题目要求的字符串Weekday().String()会返回上表右侧的字符串恰好与题目要求的七个输出值完全一致因此无需再维护任何映射表。复杂度分析time.Date的内部实现需要根据年、月、日计算从公元元年开始经过的天数进而定位到对应的星期整个过程仅涉及常数次算术运算时间复杂度为 O(1)空间复杂度为 O(1)。经典算法补充不依赖标准库的星期计算time包虽然一行搞定但在面试手写场景或某些不支持标准库的环境中通常需要自行实现。这里补充两类最常见的经典算法作为原理性参考并非本仓库源码内容。蔡勒公式Zellers Congruence蔡勒公式是计算格里高利历公历日期对应星期几的经典公式其形式为h (q ⌊13(m1)/5⌋ K ⌊K/4⌋ ⌊J/4⌋ 5J) mod 7其中h为计算结果0表示星期六1表示星期日……6表示星期五q为日m为月3 月到 12 月取值 3~121 月和 2 月需视为上一年的 13 月和 14 月即m month 12同时year减 1K为年份后两位J为年份前两位世纪数。由于题目约束年份在 19712100 之间全部属于格里高利历范围因此该公式完全适用。实现时注意把h的结果映射回题目要求的{Sunday, ..., Saturday}序列即可。Sakamoto 算法Sakamoto 算法是一种基于预计算月份偏移表的紧凑实现它维护一张长度为 12 的偏移表t[] {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}核心步骤为当月份小于 3 时年份减 1然后计算weekday (year year/4 - year/100 year/400 t[month-1] day) % 7结果0对应星期日1对应星期一依此类推。相比蔡勒公式Sakamoto 算法只依赖一张小表和一次取模代码更短是竞赛圈里非常流行的手写方案。基准日累加法最朴素的自实现思路是选定一个已知星期的锚点日期例如公元 1 年 1 月 1 日是星期一然后计算从锚点到目标日期经过的总天数累加整年天数、闰年修正、各月天数与日偏移对总天数取模 7得到相对锚点星期的偏移量将偏移量映射到星期字符串。这种方式思路直白、不依赖记忆公式但代码量最大且要仔细处理闰年判定year % 4 0 (year % 100 ! 0 || year % 400 0)容易出错。相比之下time包方案在正确性上显然更有保障。测试与验证本仓库为每道题都配套了对应的单元测试文件1185 题的测试 覆盖了题目给出的全部三个示例qs : []question1185{ { para1185{31, 8, 2019}, ans1185{Saturday}, }, { para1185{18, 7, 1999}, ans1185{Sunday}, }, { para1185{15, 8, 1993}, ans1185{Sunday}, }, }测试中依次断言2019-08-31应为Saturday1999-07-18应为Sunday1993-08-15应为Sunday。三个用例分别覆盖了平年、周日与周六的不同输出验证了解法在题目约束范围内19712100 年有效日期的正确性。如何运行测试在仓库根目录下执行以下命令即可运行该题的单测go test -v ./leetcode/1185.Day-of-the-Week/如果想复现整个仓库的覆盖率统计仓库根目录的 gotest.sh 脚本提供了现成命令go test -covermodeatomic -coverprofilecoverage.txt ./leetcode/...该脚本会把leetcode目录下所有题解包括本题的覆盖率汇总输出到 coverage.txt与仓库 README 中宣称的 100% 测试覆盖率目标保持一致。小结LeetCode 1185《Day of the Week》是一道典型的日期处理入门题考察点在于是否会使用语言内置的日期时间 API——本仓库的 Go 实现通过time.Date(...).Weekday().String()三行代码含 import完成全部逻辑体现了标准库优先的工程思维代码位于 题解源码是否理解星期计算的数学原理——蔡勒公式、Sakamoto 算法等经典方案可在无标准库环境下作为替代边界处理意识——题目保证 19712100 年的有效日期简化了历法切换与日期校验的复杂度。对该题更深入的理解还可以延伸到time包内部对闰年、月长与纪元epoch的处理方式。在 LeetCode-Go 仓库中类似的日期类题目还有 1154.Day-of-the-Year一年中的第几天与 1185.Day-of-the-Week 形成呼应读者可对照阅读系统掌握 Go 日期处理技巧。【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考