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&nbsp;friends, level 2 of videos are all watched videos by the friends of your&nbsp;friends and so on. In general, the level k of videos are all&nbsp;watched videos by people&nbsp;with the shortest path exactly equal&nbsp;to&nbsp;k with you. Given your&nbsp;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.&nbsp;

&nbsp;
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 -&gt; watchedVideos = ["C"]&nbsp;
Person with id = 2 -&gt; watchedVideos = ["B","C"]&nbsp;
The frequencies of watchedVideos by your friends are:&nbsp;
B -&gt; 1&nbsp;
C -&gt; 2


Example 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).


&nbsp;
Constraints:


	n == watchedVideos.length ==&nbsp;friends.length
	2 &lt;= n&nbsp;&lt;= 100
	1 &lt;=&nbsp;watchedVideos[i].length &lt;= 100
	1 &lt;=&nbsp;watchedVideos[i][j].length &lt;= 8
	0 &lt;= friends[i].length &lt; n
	0 &lt;= friends[i][j]&nbsp;&lt; n
	0 &lt;= id &lt; n
	1 &lt;= level &lt; n
	if&nbsp;friends[i] contains j, then friends[j] contains i


class Solution:
	def watchedVideosByFriends(self, watchedVideos: List[List[str]], friends: List[List[int]], id: int, level: int) -> List[str]:
		q=[id]
		vis=set([id])
		l=0
		while l<level:
			new_q=[]
			for x in q:
				for friend in friends[x]:
					if not friend in vis:
						vis.add(friend)
						new_q.append(friend)
			q=new_q
			l+=1
		a=Counter()
		for x in q:
			for vids in watchedVideos[x]:
				a[vids]+=1
		A=sorted([[a[x],x] for x in a])
		return [x[1] for x in A]
class Solution {
    public List<String> watchedVideosByFriends(List<List<String>> watchedVideos, int[][] friends, int id, int level) {
        int n = friends.length;
        boolean[] visited = new boolean[n];
        List<List<Integer>> graph = new ArrayList<>();
        for(int i=0;i<n;i++) graph.add(new ArrayList<>());
        for(int i=0;i<n;i++){
            for(int j=0;j<friends[i].length;j++){
                graph.get(i).add(friends[i][j]);
            }
        }
        // System.out.println(graph.get(0));
        Queue<Integer> queue = new ArrayDeque<>();
        queue.offer(id);
        visited[id] = true;
        Map<String,Integer> answer = new HashMap<>();
        while(!queue.isEmpty() && level>0){
            int size = queue.size();
            for(int i=0;i<size;i++){
                int vertex = queue.remove();
                for(int child: graph.get(vertex)){
                    if(!visited[child]){
                        //   if(level == 1) System.out.println(watchedVideos.get(child));
                        if(level == 1) {
                            for(String a: watchedVideos.get(child)){
                                answer.put(a,answer.getOrDefault(a,0)+1);
                            }
                        }
                        visited[child] = true;
                        queue.offer(child);
                    }
                }
            }
            level--;
        }
        Queue<String[]> sortedQueue = new PriorityQueue<>((a,b)->{
            if(a[1].equals(b[1])) return a[0].compareTo(b[0]);
            return Integer.parseInt(a[1])-Integer.parseInt(b[1]);
        });
        for(String key: answer.keySet()){
            sortedQueue.offer(new String[]{key,Integer.toString(answer.get(key))});
        }
        List<String> finalAnswer = new ArrayList<>();
        while(!sortedQueue.isEmpty()) finalAnswer.add(sortedQueue.remove()[0]);
        return finalAnswer;
    }
}
class Solution {
public:
  vector<string> watchedVideosByFriends(vector<vector<string>>& watchedVideos, vector<vector<int>>& friends, int id, int level) {
    vector<vector<int>>graph(watchedVideos.size());
    
    for(int i = 0;i != friends.size(); i++)
      for(auto &f: friends[i])
        graph[f].push_back(i), graph[i].push_back(f);
    
    int tmp_level = 0;
    vector<int>vis(watchedVideos.size(),0);
    vector<string>ans;
    
    queue<int>q;
    q.push(id);
    while(!q.empty()){
      if(tmp_level++ == level){
        unordered_map<string,int>mp;
        while(!q.empty()){
          int t = q.front(); q.pop();
          if(vis[t])continue;
          vis[t] = 1;
          for(auto &v: watchedVideos[t]) mp[v]++;
        }
        set<pair<int,string>>st;  
        for(auto &[s, n]: mp) st.insert({n,s});
        for(auto &it: st) ans.push_back(it.second);
      }
                    
      int n = q.size();
      while(n--){
        int t = q.front(); q.pop();
        if(vis[t])continue;
        vis[t] = 1;
        
        for(auto &x: graph[t])
          if(!vis[x]) q.push(x);
      }
    }
    
    return ans;
  }
};
/**
 * @param {string[][]} watchedVideos
 * @param {number[][]} friends
 * @param {number} id
 * @param {number} level
 * @return {string[]}
 */
var watchedVideosByFriends = function(watchedVideos, friends, id, level) {
  const queue = [];
  queue.push([id, 0]);
  const seen = new Set();
  const map = {};

  while (queue.length > 0) {
    const [id, _level] = queue.shift();
    if (seen.has(id)) {
      continue;
    }
    seen.add(id);
    if (_level == level) {
      for (const video of watchedVideos[id]) {
        if (!map[video]) {
          map[video] = 1
        } else {
          map[video] += 1;
        }
      }
      continue;
    }

    for (const f of friends[id]) {
      queue.push([f, _level + 1]);
    }
  }

  return Object.keys(map).sort((a, b) => {
    const diff = map[a] - map[b];
    if (diff == 0) {
      return a.localeCompare(b);
    }
    return diff;
  })
};
Get Watched Videos by Your Friends