Leap Year
You get a year year of the Gregorian calendar. Return true if it is a leap year, the kind that has a 29th of February, and false otherwise.
A year is a leap year when it is divisible by 4, except for years divisible by 100, which are not leap years unless they are also divisible by 400.
Function
- yearinteger
- the year to check
- Returnsboolean
- true when the year has a 29th of February, false otherwise
Constraints
1 ≤ year ≤ 106
Examples
- Input
- year = 2024
- Output
- true
- Explanation
2024is divisible by4and is not a century year, so it is a leap year.
- Input
- year = 1900
- Output
- false
- Explanation
1900is divisible by4, but it is also divisible by100and not by400, so the century exception applies and it is not a leap year.
- Input
- year = 2000
- Output
- true
- Explanation
2000is divisible by100, which would rule it out, but it is also divisible by400, which brings it back. It is a leap year.
+16 hidden tests on Submit
Hints
Open them one at a time. Each one gives away a little more.
A remainder of
0after dividing by4is the first rule. Which years break it?Century years break it, and multiples of
400break the century rule in turn. Every multiple of400is also a multiple of100and of4, so the order of your checks decides the answer.Check divisibility by
400first, then by100, then by4, and let the first rule that matches decide. Or combine them: divisible by 4 and not by 100, or divisible by 400.
Solution
Each rule needs only one remainder, so the work is three divisibility checks. The trap is the order: the rules contradict each other on years like 2000, which is a century and also a multiple of 400. Either test the most specific rule first, or write the rule as one expression whose parentheses keep the exceptions in their place.
Check the rules from most specific to least
Intuition
The three rules form a chain of exceptions. Divisible by 4 makes a year leap, divisible by 100 undoes that, and divisible by 400 undoes the undo. A year that matches a later rule always matches the earlier ones too: every multiple of 400 is a multiple of 100, and every multiple of 100 is a multiple of 4.
So the most specific rule that matches decides the answer. Test 400 first, then 100, then 4, and return as soon as one matches. For 2000 the first test already says yes. For 1900 the first test fails and the second says no. For 2024 the first two fail and the third says yes.
If none of the three matches, the year is not divisible by 4 at all, so it is an ordinary year.
Algorithm
- If
year % 400 == 0, returntrue. - If
year % 100 == 0, returnfalse. - If
year % 4 == 0, returntrue. - Otherwise return
false.
def isLeapYear(year):
if year % 400 == 0:
return True
if year % 100 == 0:
return False
if year % 4 == 0:
return True
return FalseOne boolean expression
Intuition
Read the rule as two ways to be a leap year. Either the year is divisible by 4 and is not a century, or it is divisible by 400. That sentence translates word for word into (year % 4 == 0 and year % 100 != 0) or year % 400 == 0.
Check it on the three examples. 2024 passes the first half. 1900 fails the first half because it is a century, and fails the second because 1900 % 400 is 300. 2000 fails the first half for the same reason as 1900, and passes the second.
You can also group it the other way: divisible by 4, and either not a century or a multiple of 400. Both forms agree on every year. The expression does at most the same three checks as the if chain.
Algorithm
- Compute
year % 4 == 0 and year % 100 != 0: divisible by 4 and not a century. - Compute
year % 400 == 0. - Return
trueif either part holds.
def isLeapYear(year):
# Every 4th year, except centuries, except every 400th year.
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
Pitfalls and edge cases
Every mistake here comes from treating the rule as one test instead of a chain of exceptions.
- Checking only
year % 4 == 0. It gives the right answer for every year from1901to2099, which is why the bug hides, and the wrong answer for1900and2100. - Testing
100before400in an if chain. The century test returnsfalsefor2000before the400test ever runs. - Dropping the divisible by 4 part.
year % 100 != 0 or year % 400 == 0calls2023a leap year, because2023is not a century. - Using
year / 4where you meant the remainder. Division tells you how many times4fits; the remainder tells you whether it fits exactly.
Frequently asked questions4
What is the rule for a leap year?
A Gregorian year is a leap year when it is divisible by 4, unless it is divisible by 100. A year divisible by 400 is a leap year anyway. So 2024 and 2000 are leap years, while 1900 and 2100 are not.
Why is 1900 not a leap year but 2000 is?
Both are century years, divisible by 100, which normally rules a year out. 2000 is also divisible by 400, and that rule overrides the century rule. 1900 leaves a remainder of 300 when divided by 400, so it stays an ordinary year.
Why do the century rules exist?
A solar year lasts about 365.2422 days. Adding a day every 4 years gives an average of 365.25, which is about 3 days too many every 400 years. Skipping the leap day in 3 of every 4 century years removes those 3 days. The average becomes 365.2425 days, close enough to keep the calendar in step with the seasons for thousands of years.
What is the time complexity of checking a leap year?
It is O(1) in time and space. The check is at most three remainder operations and a few comparisons, whatever the size of the year.
Similar problems
Problems that use the same ideas. Solving two or three of them is what makes a pattern stick.
Python
def isLeapYear(year):
# Write code hereCase 1
Case 2
Case 3
Input
year = 2024
Expected
true