Friends Of Appropriate Ages solution and explanation
9 more videos on this problem
Leetcode 825 Friends Of Appropriate AgesRen Zhang · 10:39 · 5K views
Facebook Coding Interview Question | Leetcode 825 | Friends Of Appropriate AgesWorkWithGoogler · 15:52 · 3K views
825. Friends Of Appropriate Ages (Leetcode Medium)Programming Live with Larry · 14:53 · 1K views
Leetcode 825(medium). Friends of Appropriate Ages【Array】中文AndroidBabies安卓大宝贝们 · 21:16 · 715 views
LeetCode 825. Friends Of Appropriate Ages | JSer - JavaScript & AlgorithmJSer · 34:01 · 605 views
小旭讲解 LeetCode 825. Friends Of Appropriate Ages - EP29HU Xiaoxu · 13:44 · 588 views
825. Friends Of Appropriate AgesJust Coding, with Jie · 13:04 · 572 views
Friends Of Appropriate Ages || Coder Army || Lec :- 9Byte Benders · 13:54 · 516 views
Friends Of Appropriate AgesOwen Wu · 1:57 · 509 views
LEETCODE 825. Friends Of Appropriate Ages (中文 | Java)和歌山小喵 · 2:37 · 369 views
The problem
There are n persons on a social media website. You are given an integer array ages where ages[i] is the age of the ith person.
A Person x will not send a friend request to a person y (x != y) if any of the following conditions is true:
age[y] <= 0.5 * age[x] + 7age[y] > age[x]age[y] > 100 && age[x] < 100
Otherwise, x will send a friend request to y.
Note that if x sends a request to y, y will not necessarily send a request to x. Also, a person will not send a friend request to themself.
Return the total number of friend requests made.
Example 1:
Input: ages = [16,16] Output: 2 Explanation: 2 people friend request each other.
Example 2:
Input: ages = [16,17,18] Output: 2 Explanation: Friend requests are made 17 -> 16, 18 -> 17.
Example 3:
Input: ages = [20,30,100,110,120] Output: 3 Explanation: Friend requests are made 110 -> 100, 120 -> 110, 120 -> 100.
Constraints:
n == ages.length1 <= n <= 2 * 1041 <= ages[i] <= 120
Approach overview
Problem Overview: You receive an array where ages[i] represents a person's age. A person A can send a friend request to B only if specific age constraints are satisfied. The task is to count how many valid friend requests are sent across the entire group. The challenge is avoiding unnecessary pair checks when the input size grows.
Approach 1: Brute Force Pair Checking (Time: O(n2), Space: O(1))
Iterate through every pair of people using two nested loops. For each pair (i, j), verify the three rules: age[j] > 0.5 * age[i] + 7, age[j] <= age[i], and the special constraint involving ages above 100. If the conditions pass, count the request. This approach directly models the problem logic and is easy to implement, but it performs a comparison for every pair. With up to thousands of people, the O(n²) time complexity becomes expensive. It works well only for small inputs or when validating the rules during initial problem exploration using basic array traversal.
Approach 2: Optimized Counting with Age Frequency (Time: O(n + A2), Space: O(A))
Instead of checking every pair of individuals, count how many people have each age. Since ages range only from 1 to 120, build a frequency array where count[a] stores how many people are age a. Then iterate over all age pairs (ageA, ageB). If the friend request rules allow someone of age ageA to send a request to ageB, add count[ageA] * count[ageB] to the result. When ageA == ageB, subtract self-requests because a person cannot send a request to themselves.
This optimization dramatically reduces work because you evaluate at most 120 × 120 age combinations instead of n² people combinations. The idea relies on grouping values and applying conditions to aggregated counts. You can also improve the constant factor by sorting the ages and using two pointers or binary search to locate valid ranges for each age. All these variants rely on the same insight: friend requests depend only on age ranges, not individual identities.
Recommended for interviews: Interviewers expect you to move beyond the brute force check quickly. Starting with the O(n²) approach shows you understand the request rules. The optimized counting or sorted two-pointer method demonstrates algorithmic thinking and reduces the complexity to roughly O(n + A²) (with A = 120) or near-linear time after sorting. That improvement is the key signal of strong problem-solving skill.
Approach 1: Brute Force Approach
In this approach, we will use two nested loops to check all possible pairs of people. For each pair, we will check the conditions provided in the problem to determine if a friend request should be sent. Though simple, this approach can be inefficient for larger datasets.
class Solution:
def numFriendRequests(self, ages):
count = 0
for i in range(len(ages)):
for j in range(len(ages)):
if i != j:
if not (ages[j] <= 0.5 * ages[i] + 7 or ages[j] > ages[i] or (ages[j] > 100 and ages[i] < 100)):
count += 1
return count
# Example Usage
sol = Solution()
print(sol.numFriendRequests([16, 16])) # Output: 2
print(sol.numFriendRequests([16, 17, 18])) # Output: 2
print(sol.numFriendRequests([20, 30, 100, 110, 120])) # Output: 3import java.util.List;
public class Solution {
public int numFriendRequests(int[] ages) {
int count = 0;
for (int i = 0; i < ages.length; i++) {
for (int j = 0; j < ages.length; j++) {
if (i != j) {
if (!(ages[j] <= 0.5 * ages[i] + 7 || ages[j] > ages[i] || (ages[j] > 100 && ages[i] < 100))) {
count++;
}
}
}
}
return count;
}
public static void main(String[] args) {
Solution sol = new Solution();
int[] ages1 = {16, 16};
System.out.println(sol.numFriendRequests(ages1)); // Output: 2
int[] ages2 = {16, 17, 18};
System.out.println(sol.numFriendRequests(ages2)); // Output: 2
int[] ages3 = {20, 30, 100, 110, 120};
System.out.println(sol.numFriendRequests(ages3)); // Output: 3
}
}#include <vector>
using namespace std;
class Solution {
public:
int numFriendRequests(vector<int>& ages) {
int count = 0;
for (int i = 0; i < ages.size(); ++i) {
for (int j = 0; j < ages.size(); ++j) {
if (i != j) {
if (!(ages[j] <= 0.5 * ages[i] + 7 || ages[j] > ages[i] || (ages[j] > 100 && ages[i] < 100))) {
count++;
}
}
}
}
return count;
}
};
int main() {
Solution sol;
vector<int> ages1 = {16, 16};
printf("%d\n", sol.numFriendRequests(ages1)); // Output: 2
vector<int> ages2 = {16, 17, 18};
printf("%d\n", sol.numFriendRequests(ages2)); // Output: 2
vector<int> ages3 = {20, 30, 100, 110, 120};
printf("%d\n", sol.numFriendRequests(ages3)); // Output: 3
return 0;
}function numFriendRequests(ages) {
let count = 0;
for (let i = 0; i < ages.length; i++) {
for (let j = 0; j < ages.length; j++) {
if (i !== j) {
if (!(ages[j] <= 0.5 * ages[i] + 7 || ages[j] > ages[i] || (ages[j] > 100 && ages[i] < 100))) {
count++;
}
}
}
}
return count;
}
console.log(numFriendRequests([16, 16])); // Output: 2
console.log(numFriendRequests([16, 17, 18])); // Output: 2
console.log(numFriendRequests([20, 30, 100, 110, 120])); // Output: 3#include <stdio.h>
int numFriendRequests(int* ages, int agesSize) {
int count = 0;
for (int i = 0; i < agesSize; i++) {
for (int j = 0; j < agesSize; j++) {
if (i != j) {
if (!(ages[j] <= 0.5 * ages[i] + 7 || ages[j] > ages[i] || (ages[j] > 100 && ages[i] < 100))) {
count++;
}
}
}
}
return count;
}
int main() {
int ages1[] = {16, 16};
printf("%d\n", numFriendRequests(ages1, 2)); // Output: 2
int ages2[] = {16, 17, 18};
printf("%d\n", numFriendRequests(ages2, 3)); // Output: 2
int ages3[] = {20, 30, 100, 110, 120};
printf("%d\n", numFriendRequests(ages3, 5)); // Output: 3
return 0;
}public class Solution {
public int NumFriendRequests(int[] ages) {
int count = 0;
for (int i = 0; i < ages.Length; i++) {
for (int j = 0; j < ages.Length; j++) {
if (i != j && !(ages[j] <= 0.5 * ages[i] + 7 || ages[j] > ages[i] || (ages[j] > 100 && ages[i] < 100))) {
count++;
}
}
}
return count;
}
public static void Main(string[] args) {
Solution sol = new Solution();
Console.WriteLine(sol.NumFriendRequests(new int[] { 16, 16 })); // Output: 2
Console.WriteLine(sol.NumFriendRequests(new int[] { 16, 17, 18 })); // Output: 2
Console.WriteLine(sol.NumFriendRequests(new int[] { 20, 30, 100, 110, 120 })); // Output: 3
}
}The Python solution uses two nested loops, iterating through all combinations of pairs and applying the relevant conditions for valid friend requests.
Time Complexity: O(n^2)
Space Complexity: O(1)
Approach 2: Optimized Counting Approach
To optimize the previous brute force solution, we can use counting to reduce the number of comparisons. By first counting the occurrences of each age, we minimize unnecessary comparisons through sorted age analysis.
class Solution:
def numFriendRequests(self, ages):
from collections import Counter
count = Counter(ages)
requests = 0
for ageA in count:
for ageB in count:
if not (ageB <= 0.5 * ageA + 7 or ageB > ageA or (ageB > 100 and ageA < 100)):
if ageA == ageB:
requests += count[ageA] * (count[ageB] - 1)
else:
requests += count[ageA] * count[ageB]
return requests
# Example Usage
sol = Solution()
print(sol.numFriendRequests([16, 16])) # Output: 2
print(sol.numFriendRequests([16, 17, 18])) # Output: 2
print(sol.numFriendRequests([20, 30, 100, 110, 120])) # Output: 3import java.util.Arrays;
public class Solution {
public int numFriendRequests(int[] ages) {
int[] count = new int[121];
for (int age : ages) {
count[age]++;
}
int requests = 0;
for (int ageA = 0; ageA < 121; ageA++) {
for (int ageB = 0; ageB < 121; ageB++) {
if (count[ageA] > 0 && count[ageB] > 0) {
if (!(ageB <= 0.5 * ageA + 7 || ageB > ageA || (ageB > 100 && ageB > 100 && ageA < 100))) {
requests += count[ageA] * (count[ageB] - (ageA == ageB ? 1 : 0));
}
}
}
}
return requests;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.numFriendRequests(new int[] {16, 16})); // Output: 2
System.out.println(sol.numFriendRequests(new int[] {16, 17, 18})); // Output: 2
System.out.println(sol.numFriendRequests(new int[] {20, 30, 100, 110, 120})); // Output: 3
}
}#include <vector>
using namespace std;
#define MAX_AGE 121
class Solution {
public:
int numFriendRequests(vector<int>& ages) {
vector<int> count(MAX_AGE, 0);
for (int age : ages) {
count[age]++;
}
int requests = 0;
for (int ageA = 0; ageA < MAX_AGE; ageA++) {
for (int ageB = 0; ageB < MAX_AGE; ageB++) {
if (count[ageA] > 0 && count[ageB] > 0) {
if (!(ageB <= 0.5 * ageA + 7 || ageB > ageA || (ageB > 100 && ageA < 100))) {
requests += count[ageA] * (count[ageB] - (ageA == ageB));
}
}
}
}
return requests;
}
};
int main() {
Solution sol;
vector<int> ages1 = {16, 16};
printf("%d\n", sol.numFriendRequests(ages1)); // Output: 2
vector<int> ages2 = {16, 17, 18};
printf("%d\n", sol.numFriendRequests(ages2)); // Output: 2
vector<int> ages3 = {20, 30, 100, 110, 120};
printf("%d\n", sol.numFriendRequests(ages3)); // Output: 3
return 0;
}function numFriendRequests(ages) {
const MAX_AGE = 121;
const count = new Array(MAX_AGE).fill(0);
ages.forEach(age => count[age]++);
let requests = 0;
for (let ageA = 0; ageA < MAX_AGE; ageA++) {
for (let ageB = 0; ageB < MAX_AGE; ageB++) {
if (count[ageA] > 0 && count[ageB] > 0) {
if (!(ageB <= 0.5 * ageA + 7 || ageB > ageA || (ageB > 100 && ageA < 100))) {
requests += count[ageA] * (count[ageB] - (ageA === ageB ? 1 : 0));
}
}
}
}
return requests;
}
console.log(numFriendRequests([16, 16])); // Output: 2
console.log(numFriendRequests([16, 17, 18])); // Output: 2
console.log(numFriendRequests([20, 30, 100, 110, 120])); // Output: 3#include <stdio.h>
#include <memory.h>
define MAX_AGE 121
int numFriendRequests(int* ages, int agesSize) {
int count[MAX_AGE] = {0};
for (int i = 0; i < agesSize; i++) {
count[ages[i]]++;
}
int requests = 0;
for (int ageA = 0; ageA < MAX_AGE; ageA++) {
for (int ageB = 0; ageB < MAX_AGE; ageB++) {
if (count[ageA] > 0 && count[ageB] > 0) {
if (!(ageB <= 0.5 * ageA + 7 || ageB > ageA || (ageB > 100 && ageA < 100))) {
requests += count[ageA] * (count[ageB] - (ageA == ageB));
}
}
}
}
return requests;
}
int main() {
int ages1[] = {16, 16};
printf("%d\n", numFriendRequests(ages1, 2)); // Output: 2
int ages2[] = {16, 17, 18};
printf("%d\n", numFriendRequests(ages2, 3)); // Output: 2
int ages3[] = {20, 30, 100, 110, 120};
printf("%d\n", numFriendRequests(ages3, 5)); // Output: 3
return 0;
}using System;
public class Solution {
public int NumFriendRequests(int[] ages) {
int[] count = new int[121];
foreach (int age in ages) {
count[age]++;
}
int requests = 0;
for (int ageA = 0; ageA < 121; ageA++) {
for (int ageB = 0; ageB < 121; ageB++) {
if (count[ageA] > 0 && count[ageB] > 0) {
if (!(ageB <= 0.5 * ageA + 7 || ageB > ageA || (ageB > 100 && ageA < 100))) {
requests += count[ageA] * (count[ageB] - (ageA == ageB ? 1 : 0));
}
}
}
}
return requests;
}
public static void Main() {
Solution sol = new Solution();
Console.WriteLine(sol.NumFriendRequests(new int[] { 16, 16 })); // Output: 2
Console.WriteLine(sol.NumFriendRequests(new int[] { 16, 17, 18 })); // Output: 2
Console.WriteLine(sol.NumFriendRequests(new int[] { 20, 30, 100, 110, 120 })); // Output: 3
}
}Using Python's collections framework, we keep track of each age's frequency, minimizing pairwise comparisons, leading to an efficient solution.
Time Complexity: O(MAX_AGE^2) = O(121^2)
Space Complexity: O(MAX_AGE) = O(121)
Approach 3: Counting + Enumeration
We can use an array cnt of length 121 to record the number of people of each age.
Next, we enumerate all possible age pairs (ax, ay). If ax and ay satisfy the conditions given in the problem, these age pairs (ax, ay) can send friend requests to each other.
If ax = ay, meaning the ages are the same, then the number of friend requests between ax and ay is cnt[ax] times (cnt[ax] - 1). Otherwise, if the ages are different, the number of friend requests between ax and ay is cnt[ax] times cnt[ay]. We accumulate these friend request counts into the answer.
The time complexity is O(n + m^2), where n is the length of the array ages, and m is the maximum age, which is 121 in this problem.
function numFriendRequests(ages: number[]): number {
const m = 121;
const cnt = Array(m).fill(0);
for (const x of ages) {
cnt[x]++;
}
let ans = 0;
for (let ax = 0; ax < m; ax++) {
for (let ay = 0; ay < m; ay++) {
if (ay <= 0.5 * ax + 7 || ay > ax || (ay > 100 && ax < 100)) {
continue;
}
ans += cnt[ax] * (cnt[ay] - (ax === ay ? 1 : 0));
}
}
return ans;
}func numFriendRequests(ages []int) (ans int) {
cnt := [121]int{}
for _, x := range ages {
cnt[x]++
}
for ax, x := range cnt {
for ay, y := range cnt {
if ay <= ax/2+7 || ay > ax || (ay > 100 && ax < 100) {
continue
}
if ax == ay {
ans += x * (x - 1)
} else {
ans += x * y
}
}
}
return
}Complexity comparison
| Approach | Complexity |
|---|---|
| Brute Force Approach | Time Complexity: O(n^2) |
| Optimized Counting Approach | Time Complexity: O(MAX_AGE^2) = O(121^2) |
| Counting + Enumeration | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Pair Check | O(n²) | O(1) | Good for understanding the request rules or when input size is very small |
| Sorting + Two Pointers | O(n log n) | O(1) | Useful when working directly on the sorted ages array and finding valid ranges efficiently |
| Counting by Age Frequency (Optimal) | O(n + A²) | O(A) | Best when ages are within a small fixed range (1–120), allowing aggregated counting |
Frequently asked questions
Is Friends Of Appropriate Ages easy or hard?
Friends Of Appropriate Ages is rated Medium difficulty. The rules for valid requests are straightforward, but the challenge is recognizing that checking every pair is inefficient. Efficient solutions rely on sorting, two pointers, or counting techniques.
Friends Of Appropriate Ages Python/Java solution
Python and Java implementations typically follow the same idea: either sort the ages and use two pointers to find valid ranges, or build a frequency array of size 121 and compute valid age combinations. Both approaches significantly reduce unnecessary pair comparisons.
How to solve Friends Of Appropriate Ages in O(n)?
A near-linear solution uses an age frequency array and prefix counts. Instead of evaluating each person pair, count how many people exist for each age and compute valid ranges that satisfy the request rules. Because the age range is limited to 120 values, the computation effectively behaves like O(n).
What is the best approach for Friends Of Appropriate Ages?
The most efficient approach counts how many people have each age and evaluates valid age pairs instead of individual pairs. Since ages range from 1 to 120, you can iterate through all age combinations and apply the friend request rules. This reduces the complexity to roughly O(n + A^2) where A is the age range (120), making it far faster than O(n^2).
Is Friends Of Appropriate Ages asked at Google/Amazon/Meta?
Friends Of Appropriate Ages appears in interview preparation sets for companies such as Amazon, Google, and Meta because it tests reasoning with constraints, counting optimizations, and range-based conditions. The problem also evaluates your ability to move from brute force to aggregated counting or two-pointer techniques.
What data structure is used in Friends Of Appropriate Ages?
The common solutions use arrays for age storage and a frequency array for counting how many people share the same age. Some implementations also use sorting combined with two pointers or binary search to find valid age ranges efficiently.
What is the time complexity of Friends Of Appropriate Ages?
The brute force solution runs in O(n^2) because every pair of people must be checked. The optimized counting approach runs in O(n + A^2), where A is the maximum possible age (120). Sorting-based solutions run in O(n log n) followed by linear scans with two pointers.
