There are n people, each person has a unique id between 0 and n-1. Given the arrays watchedVideos and friends, where watchedVideos[i] and friends[i] contain the list of watched videos and the list of friends respectively for the person with id i.
Level 1 of videos are all watched videos by your friends, level 2 of videos are all watched videos by the friends of your friends and so on. In general, the level k of videos are all watched videos by people with the shortest path exactly equal to k with you.
Given your id and the level of videos, return the list of videos ordered by their frequencies (increasing). For videos with the same frequency order them alphabetically from least to greatest.
💡 Note:Person 0's friends are 1 and 2 (level 1). Person 1 watched ["C"], Person 2 watched ["B","C"]. Video counts: B=1, C=2. Sorted by frequency: ["B","C"]
The key insight is to use BFS to find friends at exactly the target level distance. BFS naturally finds shortest paths, ensuring we get friends at the precise level. The optimal approach processes entire levels at once and uses early termination for maximum efficiency. After collecting friends at the target level, count video frequencies and sort by frequency first, then alphabetically.
Common Approaches
✓
BFS Shortest Path
⏱️ Time: O(n + E + V log V)
Space: O(n + V)
This approach uses breadth-first search to explore the friend network level by level, ensuring we find the shortest path to each person. We stop at the target level and collect videos from all friends at that exact distance.
Brute Force with DFS
⏱️ Time: O(n^level + V log V)
Space: O(n + V)
This approach uses depth-first search to explore all paths from the starting person and identify friends at exactly the target level. It then aggregates all videos watched by these friends and sorts by frequency and alphabetically.
Optimized BFS with Early Termination
⏱️ Time: O(n + E + V log V)
Space: O(n + V)
This optimized approach uses BFS with early termination - once we've processed all nodes at the target level, we stop the search entirely. This avoids unnecessary exploration of deeper levels and provides the best performance.
BFS Shortest Path — Algorithm Steps
Initialize BFS queue with starting person at level 0
Process each level completely before moving to next
Track visited nodes to avoid revisiting
When reaching target level, collect all people at that level
Count video frequencies and sort results
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Initialize Queue
Start with person 0 at level 0 in queue
2
Process Level 1
Add all direct friends to queue
3
Process Level 2
Add friends of friends to queue
4
Collect Results
Extract people at target level and count videos
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cjson/cJSON.h>
#define MAX_N 100
#define MAX_VIDEOS 1000
#define MAX_LEN 10
typedef struct {
char videos[MAX_VIDEOS][MAX_LEN];
int count[MAX_VIDEOS];
int size;
} VideoCount;
typedef struct {
int person;
int level;
} QueueItem;
char watchedVideos[MAX_N][MAX_VIDEOS][MAX_LEN];
int watchedSizes[MAX_N];
int friends[MAX_N][MAX_N];
int friendSizes[MAX_N];
int visited[MAX_N];
int n;
int compareVideos(const void* a, const void* b, void* arg) {
VideoCount* vc = (VideoCount*)arg;
char* videoA = (char*)a;
char* videoB = (char*)b;
int countA = 0, countB = 0;
for (int i = 0; i < vc->size; i++) {
if (strcmp(vc->videos[i], videoA) == 0) countA = vc->count[i];
if (strcmp(vc->videos[i], videoB) == 0) countB = vc->count[i];
}
if (countA != countB) return countA - countB;
return strcmp(videoA, videoB);
}
void solution() {
char line[10000];
fgets(line, sizeof(line), stdin);
cJSON* watchedJson = cJSON_Parse(line);
fgets(line, sizeof(line), stdin);
cJSON* friendsJson = cJSON_Parse(line);
fgets(line, sizeof(line), stdin);
int id = atoi(line);
fgets(line, sizeof(line), stdin);
int level = atoi(line);
n = cJSON_GetArraySize(watchedJson);
for (int i = 0; i < n; i++) {
cJSON* personVideos = cJSON_GetArrayItem(watchedJson, i);
watchedSizes[i] = cJSON_GetArraySize(personVideos);
for (int j = 0; j < watchedSizes[i]; j++) {
strcpy(watchedVideos[i][j], cJSON_GetStringValue(cJSON_GetArrayItem(personVideos, j)));
}
cJSON* personFriends = cJSON_GetArrayItem(friendsJson, i);
friendSizes[i] = cJSON_GetArraySize(personFriends);
for (int j = 0; j < friendSizes[i]; j++) {
friends[i][j] = cJSON_GetNumberValue(cJSON_GetArrayItem(personFriends, j));
}
}
QueueItem queue[MAX_N * MAX_N];
int front = 0, rear = 0;
int friendsAtLevel[MAX_N];
int friendsAtLevelSize = 0;
memset(visited, 0, sizeof(visited));
queue[rear++] = (QueueItem){id, 0};
visited[id] = 1;
while (front < rear) {
QueueItem current = queue[front++];
if (current.level == level) {
friendsAtLevel[friendsAtLevelSize++] = current.person;
continue;
}
if (current.level < level) {
for (int i = 0; i < friendSizes[current.person]; i++) {
int friend_id = friends[current.person][i];
if (!visited[friend_id]) {
visited[friend_id] = 1;
queue[rear++] = (QueueItem){friend_id, current.level + 1};
}
}
}
}
VideoCount vc = {0};
for (int i = 0; i < friendsAtLevelSize; i++) {
int person = friendsAtLevel[i];
for (int j = 0; j < watchedSizes[person]; j++) {
char* video = watchedVideos[person][j];
int found = -1;
for (int k = 0; k < vc.size; k++) {
if (strcmp(vc.videos[k], video) == 0) {
found = k;
break;
}
}
if (found >= 0) {
vc.count[found]++;
} else {
strcpy(vc.videos[vc.size], video);
vc.count[vc.size] = 1;
vc.size++;
}
}
}
qsort_r(vc.videos, vc.size, MAX_LEN, compareVideos, &vc);
printf("[");
for (int i = 0; i < vc.size; i++) {
printf("\"%s\"", vc.videos[i]);
if (i < vc.size - 1) printf(",");
}
printf("]\n");
cJSON_Delete(watchedJson);
cJSON_Delete(friendsJson);
}
int main() {
solution();
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n + E + V log V)
BFS traversal of graph plus sorting videos
n
2n
⚡ Linearithmic
Space Complexity
O(n + V)
Queue for BFS and storage for videos
n
2n
⚡ Linearithmic Space
28.0K Views
MediumFrequency
~25 minAvg. Time
892 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.