Leap Year Check
Description
Given a year, return true if it is a leap year and false if it isn't.
In the Gregorian calendar a year is a leap year when it is divisible by 4, except century years (divisible by 100), which are leap years only when they are also divisible by 400. So 2024 and 2000 are leap years, and 1900 and 2023 aren't. Use this rule for every year in the range.
Examples
Example 1
Input: year = 2024
Output: true
Explanation: 2024 is divisible by 4 and isn't a century year, so it's a leap year.
Example 2
Input: year = 1900
Output: false
Explanation: 1900 is divisible by 4, but it's a century year not divisible by 400, so it isn't.
Example 3
Input: year = 2000
Output: true
Explanation: 2000 is a century year, but it's divisible by 400, so it is a leap year.
Example 4
Input: year = 2023
Output: false
Explanation: 2023 isn't divisible by 4.
Constraints
- 1 ≤ year ≤ 10^9
Editorial
Approach - Three Divisibility Checks
Intuition
The rule is an exception inside an exception: every 4th year is a leap year, except century years, except that every 400th year is a leap year after all. As one condition: divisible by 4 and not by 100, or divisible by 400.
year % d == 0 means d divides year. So year % 4 == 0 and year % 100 != 0 covers the ordinary leap years, and or year % 400 == 0 brings back the centuries like 2000.
Step-by-Step Explanation
Let's trace Example 2, year = 1900:
1900 % 4 = 0: a multiple of 4, so a leap year unless it's a century.1900 % 100 = 0: a century year, which needs the 400 test.1900 % 400 = 300: not divisible by 400.- A multiple of 4, but a century not divisible by 400: return
false.
Three Remainders — The remainders by 4, 100 and 400, worked out in the order the condition tests them.
Algorithm
- If
year % 4 == 0andyear % 100 != 0, returntrue: an ordinary leap year. - If
year % 400 == 0, returntrue: a century that keeps its leap day. - Otherwise return
false.
Code
class Solution {
public:
bool isLeapYear(int year) {
// every 4th year, except the centuries, except every 400th year
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
};
class Solution:
def isLeapYear(self, year: int) -> bool:
# every 4th year, except the centuries, except every 400th year
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
class Solution {
public boolean isLeapYear(int year) {
// every 4th year, except the centuries, except every 400th year
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
}
var isLeapYear = function(year) {
// every 4th year, except the centuries, except every 400th year
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
};
Complexity Analysis
Time Complexity: O(1)
Three remainders, whatever the year.
Space Complexity: O(1)
Nothing is stored.
Common Mistakes
Each of these looks right on a quick read, and the tests still reject it. The outputs below come from running the code.
Checking only for 4. return year % 4 == 0
On year = 1900 it returns true; the answer is false. Every 4th year is the old Julian rule. The Gregorian calendar drops three leap days every 400 years: a century year like 1900 is divisible by 4 but isn't a leap year.
Forgetting the 400 rule. year % 4 == 0 and year % 100 != 0
On year = 2000 it returns false; the answer is true. Centuries are skipped, but every 400th year is a leap year after all: 2000 was one. Without the year % 400 == 0 case, every century comes out as not leap.
Turning the exception around. year % 100 != 0 or year % 400 != 0
On year = 2000 it returns false; the answer is true. "Not a century, or else divisible by 400" is year % 100 != 0 or year % 400 == 0. Writing year % 400 != 0 there turns the exception around: 2000 comes out not leap and 1900 leap.
Where This Pattern Is Taught
This problem practises conditions built from remainders and joined with and and or. It's taught in Python for DSA, Java for DSA, C++ for DSA and JavaScript for DSA.