The Simplified Fractions problem asks you to generate a list of all simplified fractions between 0 and 1 (exclusive) where the denominators are less than or equal to a given integer n
. A fraction is considered simplified if the numerator and denominator are coprime (i.e., their greatest common divisor is 1).
Given an integer n
, return a list of strings representing all simplified fractions with denominators from 2 up to n
(inclusive) and numerators from 1 up to one less than the denominator.
Constraints:
1 <= n <= 100
"numerator/denominator"
.
To solve this problem, the first idea is to generate all possible fractions where the numerator is less than the denominator, and the denominator is between 2 and n
. For each possible pair, we need to check if the fraction is already simplified.
The brute-force way is to loop through every possible numerator and denominator, and for each, check if their greatest common divisor (GCD) is 1. If it is, the fraction is in its lowest terms and should be included.
The optimization comes from the realization that checking for simplification can be done efficiently using the Euclidean algorithm to compute GCD. There's no need to store or compare previously seen fractions, because the GCD check ensures uniqueness and lowest terms automatically.
This approach is direct and leverages number theory (coprimality) for correctness and efficiency.
Let's break down the algorithm step by step:
d
from 2 to n
(inclusive).d
, loop through all numerators num
from 1 to d-1
.(num, d)
, calculate the greatest common divisor (GCD).gcd(num, d) == 1
, the fraction is simplified."num/d"
to the result list.We use the Euclidean algorithm to efficiently compute the GCD, which is available as a standard library function in most languages.
Let's walk through the process with n = 4
:
The final output is: ["1/2", "1/3", "2/3", "1/4", "3/4"]
Brute-force approach:
The use of the Euclidean algorithm makes the GCD check efficient, so the solution is fast enough for the given constraints.
from math import gcd
class Solution:
def simplifiedFractions(self, n: int):
res = []
for d in range(2, n+1):
for num in range(1, d):
if gcd(num, d) == 1:
res.append(f"{num}/{d}")
return res
#include <vector>
#include <string>
#include <numeric>
using namespace std;
class Solution {
public:
vector<string> simplifiedFractions(int n) {
vector<string> res;
for (int d = 2; d <= n; ++d) {
for (int num = 1; num < d; ++num) {
if (gcd(num, d) == 1) {
res.push_back(to_string(num) + "/" + to_string(d));
}
}
}
return res;
}
};
import java.util.*;
class Solution {
public List<String> simplifiedFractions(int n) {
List<String> res = new ArrayList<>();
for (int d = 2; d <= n; d++) {
for (int num = 1; num < d; num++) {
if (gcd(num, d) == 1) {
res.add(num + "/" + d);
}
}
}
return res;
}
private int gcd(int a, int b) {
while (b != 0) {
int tmp = b;
b = a % b;
a = tmp;
}
return a;
}
}
var simplifiedFractions = function(n) {
const res = [];
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
for (let d = 2; d <= n; d++) {
for (let num = 1; num < d; num++) {
if (gcd(num, d) === 1) {
res.push(num + "/" + d);
}
}
}
return res;
};
The Simplified Fractions problem is a classic exercise in number theory and iteration. By leveraging the GCD function, we efficiently filter out only those fractions that are already in their simplest form. The approach is both intuitive and optimal for the problem constraints, making it a great example of how mathematical insight can simplify code and improve performance.