Get Watched Videos by Your Friends
MedPrompt
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.
Example 1:

Input: watchedVideos = [["A","B"],["C"],["B","C"],["D"]], friends = [[1,2],[0,3],[0,3],[1,2]], id = 0, level = 1
Output: ["B","C"]
Explanation:
You have id = 0 (green color in the figure) and your friends are (yellow color in the figure):
Person with id = 1 -> watchedVideos = ["C"]
Person with id = 2 -> watchedVideos = ["B","C"]
The frequencies of watchedVideos by your friends are:
B -> 1
C -> 2Example 2:

Input: watchedVideos = [["A","B"],["C"],["B","C"],["D"]], friends = [[1,2],[0,3],[0,3],[1,2]], id = 0, level = 2
Output: ["D"]
Explanation:
You have id = 0 (green color in the figure) and the only friend of your friends is the person with id = 3 (yellow color in the figure).
Constraints:
n == watchedVideos.length == friends.length2 <= n <= 1001 <= watchedVideos[i].length <= 1001 <= watchedVideos[i][j].length <= 80 <= friends[i].length < n0 <= friends[i][j] < n0 <= id < n1 <= level < n- if
friends[i]containsj, thenfriends[j]containsi
Approaches
2 approaches with complexity analysis and trade-offs.
This approach first identifies the friends at the specified level using a Breadth-First Search (BFS). BFS is ideal for finding all nodes at a specific distance from a source node in an unweighted graph. After finding the target friends, it collects all their watched videos into a single list. To count frequencies, it first sorts this list of videos alphabetically. This groups identical videos together, making it easy to count them in a single pass. The resulting video-frequency pairs are then sorted again based on the problem's criteria (by frequency, then alphabetically).
Algorithm
-
- Initialize a queue for BFS with
idand avisitedset containingid.
- Initialize a queue for BFS with
-
- Initialize
currentLevel = 0.
- Initialize
-
- While the queue is not empty and
currentLevel < level:
- a. Get the size of the queue for the current level.
- b. For
ifrom 0 to size-1:- i. Dequeue a person
u. - ii. For each friend
vofu:- If
vis not invisited:- Add
vtovisited. - Enqueue
v.
- Add
- If
- i. Dequeue a person
- c. Increment
currentLevel.
- While the queue is not empty and
-
- The people remaining in the queue are the friends at the target
level. If the queue is empty, return an empty list.
- The people remaining in the queue are the friends at the target
-
- Create an empty list
allVideos.
- Create an empty list
-
- For each person
pin the queue, add all their watched videos toallVideos.
- For each person
-
- Sort
allVideosalphabetically.
- Sort
-
- Create a list of pairs
videoFrequencies.
- Create a list of pairs
-
- Iterate through the sorted
allVideosto count frequencies and populatevideoFrequencies.
- Iterate through the sorted
-
- Sort
videoFrequenciesfirst by frequency (ascending) and then by video name (alphabetical).
- Sort
-
- Extract the video names from the sorted
videoFrequencieslist and return it.
- Extract the video names from the sorted
Walkthrough
The process is divided into two main phases:
-
Finding Friends at
level:- A queue is initialized with the starting
id. - A
visitedarray or set is used to keep track of people already processed to avoid cycles and redundant computations. - The BFS proceeds in levels. We iterate
leveltimes. In each iteration, we process all the people currently in the queue (a single "level" of friends), and add their unvisited friends to the queue for the next level. - After
leveliterations, the people remaining in the queue are exactly at the shortest distance oflevelfrom the startingid.
- A queue is initialized with the starting
-
Collecting, Counting, and Sorting Videos:
- All videos watched by the friends found in the previous step are aggregated into one large list.
- This list is sorted alphabetically. For example,
["C", "B", "C"]becomes["B", "C", "C"]. - We then iterate through this sorted list to count the frequency of each unique video. We can do this by keeping track of the current video and a counter. When the video changes, we store the previous video and its count.
- The list of (video, frequency) pairs is stored.
- Finally, this list of pairs is sorted. The primary sorting key is the frequency (ascending), and the secondary key is the video name (alphabetical).
- The sorted video names are extracted into the final result list.
import java.util.*; class Solution { public List<String> getWatchedVideosByYourFriends(List<List<String>> watchedVideos, int[][] friends, int id, int level) { // Step 1: BFS to find friends at the given level Queue<Integer> queue = new LinkedList<>(); queue.offer(id); boolean[] visited = new boolean[friends.length]; visited[id] = true; int currentLevel = 0; while (!queue.isEmpty() && currentLevel < level) { int size = queue.size(); for (int i = 0; i < size; i++) { int person = queue.poll(); for (int friend : friends[person]) { if (!visited[friend]) { visited[friend] = true; queue.offer(friend); } } } currentLevel++; } // Step 2: Collect all videos from friends at the target level List<String> allVideos = new ArrayList<>(); while (!queue.isEmpty()) { allVideos.addAll(watchedVideos.get(queue.poll())); } if (allVideos.isEmpty()) { return new ArrayList<>(); } // Step 3: Sort videos to count frequencies Collections.sort(allVideos); // Step 4: Count frequencies List<Map.Entry<String, Integer>> freqList = new ArrayList<>(); if (!allVideos.isEmpty()) { int count = 1; for (int i = 1; i < allVideos.size(); i++) { if (allVideos.get(i).equals(allVideos.get(i - 1))) { count++; } else { freqList.add(new AbstractMap.SimpleEntry<>(allVideos.get(i - 1), count)); count = 1; } } freqList.add(new AbstractMap.SimpleEntry<>(allVideos.get(allVideos.size() - 1), count)); } // Step 5: Sort by frequency, then by name Collections.sort(freqList, (a, b) -> { if (a.getValue().equals(b.getValue())) { return a.getKey().compareTo(b.getKey()); } return a.getValue() - b.getValue(); }); // Step 6: Extract sorted video names List<String> result = new ArrayList<>(); for (Map.Entry<String, Integer> entry : freqList) { result.add(entry.getKey()); } return result; }}Complexity
Time
O(N + E + V_total * log(V_total) + U * log(U)), where N is people, E is friendships, V_total is total videos watched by level-k friends, and U is unique videos. BFS is O(N + E). Sorting all videos is the bottleneck at O(V_total * log(V_total)).
Space
O(N + V_total), where N is the number of people and V_total is the total number of video instances. The BFS queue and visited array take O(N) space. The `allVideos` list takes O(V_total) space.
Trade-offs
Pros
Correctly solves the problem.
The BFS part is efficient for finding the friends.
Cons
The frequency counting method is inefficient. Sorting the entire list of videos (
V_total) can be slow if there are many videos and many friends.Requires multiple passes over the video data and multiple sorting operations.
Uses more intermediate memory for the
allVideoslist compared to a map-based approach.
This approach is the most efficient way to solve the problem. It also starts with a Breadth-First Search (BFS) to find the friends at the exact specified level. However, it improves upon the video processing part. Instead of collecting all videos into a list and sorting it, this method uses a Hash Map to count the frequencies of the videos in a single pass. This avoids the costly step of sorting all video occurrences. After counting, the map entries are converted to a list and sorted just once according to the problem's requirements.
Algorithm
-
- Initialize a queue for BFS with
idand avisitedset containingid.
- Initialize a queue for BFS with
-
- Initialize
currentLevel = 0.
- Initialize
-
- While the queue is not empty and
currentLevel < level:
- a. Get the size of the queue for the current level.
- b. For
ifrom 0 to size-1:- i. Dequeue a person
u. - ii. For each friend
vofu:- If
vis not invisited:- Add
vtovisited. - Enqueue
v.
- Add
- If
- i. Dequeue a person
- c. Increment
currentLevel.
- While the queue is not empty and
-
- The people remaining in the queue are the friends at the target
level.
- The people remaining in the queue are the friends at the target
-
- Create an empty Hash Map
videoFrequenciesto store(video, count).
- Create an empty Hash Map
-
- For each person
pin the queue:
- For each
videoinwatchedVideos[p]:- Increment the count for
videoin thevideoFrequenciesmap.
- Increment the count for
- For each person
-
- Create a list from the entries of the
videoFrequenciesmap.
- Create a list from the entries of the
-
- Sort this list using a custom comparator: first by frequency (ascending), then by video name (alphabetical).
-
- Create the final result list by adding the video names from the sorted list of entries.
-
- Return the result list.
Walkthrough
The overall structure is similar to the first approach but with a more optimized second phase.
-
Finding Friends at
level:- This part is identical to the first approach. A standard BFS is performed for
levelsteps to find all people at the shortest distance oflevelfromid. A queue and avisitedset are used.
- This part is identical to the first approach. A standard BFS is performed for
-
Collecting, Counting, and Sorting Videos using a Hash Map:
- A Hash Map (
Map<String, Integer>) is created to store video frequencies. - We iterate through the list of friends at the target
level. For each friend, we iterate through their list of watched videos. - For each video, we update its count in the hash map.
map.put(video, map.getOrDefault(video, 0) + 1). This single pass builds a complete frequency count of all relevant videos. - After populating the map, we extract its keys into a list.
- This list is then sorted using a custom comparator that looks up frequencies in the map. The comparator first compares entries by frequency (ascending) and then by video name (alphabetical) for ties.
- Finally, the sorted list of video names is returned.
- A Hash Map (
import java.util.*; class Solution { public List<String> getWatchedVideosByYourFriends(List<List<String>> watchedVideos, int[][] friends, int id, int level) { // Step 1: BFS to find friends at the given level Queue<Integer> queue = new LinkedList<>(); queue.offer(id); boolean[] visited = new boolean[friends.length]; visited[id] = true; int currentLevel = 0; while (!queue.isEmpty() && currentLevel < level) { int size = queue.size(); for (int i = 0; i < size; i++) { int person = queue.poll(); for (int friend : friends[person]) { if (!visited[friend]) { visited[friend] = true; queue.offer(friend); } } } currentLevel++; } // Step 2: Use a HashMap to count video frequencies Map<String, Integer> freqMap = new HashMap<>(); while (!queue.isEmpty()) { int person = queue.poll(); for (String video : watchedVideos.get(person)) { freqMap.put(video, freqMap.getOrDefault(video, 0) + 1); } } // Step 3: Create a list of videos from the map keys List<String> result = new ArrayList<>(freqMap.keySet()); // Step 4: Sort the list with a custom comparator Collections.sort(result, (a, b) -> { int freqA = freqMap.get(a); int freqB = freqMap.get(b); if (freqA != freqB) { return freqA - freqB; } return a.compareTo(b); }); return result; }}Complexity
Time
O(N + E + V_total + U * log(U)), where N is people, E is friendships, V_total is total videos, and U is unique videos. BFS is O(N + E). Populating the map is O(V_total). Sorting unique videos is O(U * log(U)). This is faster as U <= V_total.
Space
O(N + U), where N is the number of people and U is the number of unique videos. The BFS structures take O(N) space. The frequency map and result list take O(U) space.
Trade-offs
Pros
Most efficient time complexity. The frequency counting is done in linear time with respect to the total number of videos.
Optimal space complexity, as it only stores unique videos in the map.
The logic is clean and follows standard patterns for graph traversal and frequency counting.
Cons
No significant cons; this is the standard and best approach for this problem.
Solutions
Solution
class Solution {public List<String> watchedVideosByFriends(List<List<String>> watchedVideos, int[][] friends, int id, int level) { int n = friends.length; boolean[] vis = new boolean[n]; Deque<Integer> q = new LinkedList<>(); q.offerLast(id); vis[id] = true; while (level-- > 0) { for (int i = q.size(); i > 0; --i) { int u = q.pollFirst(); for (int v : friends[u]) { if (!vis[v]) { q.offerLast(v); vis[v] = true; } } } } Map<String, Integer> freq = new HashMap<>(); while (!q.isEmpty()) { for (String w : watchedVideos.get(q.pollFirst())) { freq.put(w, freq.getOrDefault(w, 0) + 1); } } List<Map.Entry<String, Integer>> t = new ArrayList<>(freq.entrySet()); t.sort((a, b)->{ if (a.getValue() > b.getValue()) { return 1; } if (a.getValue() < b.getValue()) { return -1; } return a.getKey().compareTo(b.getKey()); }); List<String> ans = new ArrayList<>(); for (Map.Entry<String, Integer> e : t) { ans.add(e.getKey()); } return ans; }}class Solution {public: vector<string> watchedVideosByFriends(vector<vector<string>> &watchedVideos, vector<vector<int>> &friends, int id, int level) { queue<int> q{{id}}; int n = friends.size(); vector<bool> vis(n); vis[id] = true; while (level--) { for (int k = q.size(); k; --k) { int i = q.front(); q.pop(); for (int j : friends[i]) { if (!vis[j]) { vis[j] = true; q.push(j); } } } } unordered_map<string, int> cnt; while (!q.empty()) { int i = q.front(); q.pop(); for (const auto &v : watchedVideos[i]) { cnt[v]++; } } vector<string> ans; for (const auto &[key, _] : cnt) { ans.push_back(key); } sort(ans.begin(), ans.end(), [&cnt](const string &a, const string &b) { return cnt[a] == cnt[b] ? a < b : cnt[a] < cnt[b]; }); return ans; }};class Solution: def watchedVideosByFriends(self, watchedVideos: List[List[str]], friends: List[List[int]], id: int, level: int, ) -> List[str]: n = len(friends) vis = [False] * n q = deque([id]) vis[id] = True for _ in range(level): size = len(q) for _ in range(size): u = q . popleft() for v in friends[u]: if not vis[v]: q . append(v) vis[v] = True freq = Counter() for _ in range(len(q)): u = q . pop() for w in watchedVideos[u]: freq[w] += 1 videos = list(freq . items()) videos . sort(key=lambda x: (x[1], x[0])) return [v[0] for v in videos]Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.