Problem Statement
You are given an integer n. You need to check if the number is a perfect number or not. Return true if it is a perfect number, otherwise, return false.
A perfect number is a positive integer that is equal to the sum of its proper divisors, excluding the number itself. For example, 6 is a perfect number because its divisors are 1, 2, and 3, and 1 + 2 + 3 = 6.
Examples
Example 1:
Input: n = 6
Output: true
Explanation: Proper divisors of 6 are 1, 2, 3.
So, 1 + 2 + 3 = 6
Example 2:
Input: n = 9
Output: false
Explanation: Proper divisors of 9 are 1, 3.
So, adding them 1 + 3 = 4.
Approaches
1️⃣ Brute Force Approach
Intuition:
Given a number, all its proper divisors (divisors that divide the number without leaving any remainder, excluding the number itself) can be found and summed up. Then, the sum can be compared with the number itself. If the sum is the same as the number, then it is a perfect number, otherwise, it is not.
Approach:
- Initialize a variable with 0 to store the sum of the proper divisors.
- Start iterating from 1 to the given number(excluding) using a loop variable, and check whether the number is divisible completely (leaving the remainder zero) by the loop variable.
- If it is divisible completely, the current value of the loop variable is a proper divisor which is added to the sum storing sum of proper divisors.
- After the sum is calculated, compare it with the given number. If found equal, the given number is perfect, otherwise, it is not.
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find whether the
number is perfect or not */
bool isPerfect(int n) {
/* Variable to store the sum
of all proper divisors */
int sum = 0;
// Loop from 1 to n
for(int i=1; i < n; ++i) {
// Check if i is a proper divisor
if(n % i == 0){
// Update sum
sum = sum + i;
}
}
// Compare sum and n
if(sum == n) return true;
return false;
}
};
int main() {
int n = 6;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find whether the
given number is perfect or not */
bool ans = sol.isPerfect(n);
if(ans) {
cout << n << " is a perfect number." << endl;
} else {
cout << n << " is not a perfect number." << endl;
}
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
– Running a loop from1 to N
. - Space Complexity:
O(1)
– Using a couple of variables i.e., constant space, regardless of the size of input.
2️⃣ Square Root (Optimal)
Intuition:
The previous approach can be optimized by using the property that for any non-negative integer n, if d is a divisor of n then n/d is also a divisor (counterpart divisor) of n. This property is symmetric about the square root of n. By traversing just the first half, the redundant iterations and computations can be avoided improving the efficiency of the algorithm.
Approach:
- Initialize a variable with 0 to store the sum of the proper divisors.
- Start iterating from 1 to square root of the given number using a loop variable, and check whether the number is divisible completely (leaving the remainder zero) by the loop variable.
- If it is divisible completely, the current value of the loop variable is a proper divisor which is added to the sum storing sum of proper divisors. Also, using the property discussed above, another proper divisor can be found.
- Note: Before adding the counterpart divisor, it should be checked if both the proper divisors are different and the counterpart divisor is not the number itself. If they are different and the counterpart divisor is not the number itself, the counterpart divisor should be added to the sum. Otherwise, the counterpart divisor should not be added to the sum ensuring that the divisor is not added twice.
- After the sum is calculated, compare it with the given number. If found equal, the given number is perfect, otherwise, it is not.
Edge Case:
- When the given number is 1, there are no proper divisors of 1, i.e., the sum of proper divisors of the number is 0. Hence, 1 is not a perfect number.
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find whether the
number is perfect or not */
bool isPerfect(int n) {
// Edge case
if(n == 1) return false;
/* Variable to store the sum
of all proper divisors */
int sum = 0;
// Loop from 1 to square root of n
for(int i=1; i <= sqrt(n); ++i) {
// Check if i is a proper divisor
if(n % i == 0){
// Update sum
sum = sum + i;
/* Add the counterpart divisor
if it's different from i and
if it is not n itself */
if(n/i != n && i != n/i) {
sum = sum + (n/i);
}
}
}
// Compare sum and n
if(sum == n) return true;
return false;
}
};
int main() {
int n = 6;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find whether the
given number is perfect or not */
bool ans = sol.isPerfect(n);
if(ans) {
cout << n << " is a perfect number." << endl;
} else {
cout << n << " is not a perfect number." << endl;
}
return 0;
}
Complexity Analysis:
- Time Complexity:
O(sqrt(N))
– Running a loop from 1 to square root of N. - Space Complexity:
O(1)
– Using a couple of variables i.e., constant space, regardless of the size of input.