Skip to content

2254. Design Video Sharing Platform 👍

  • Time:
    • Constructor: $O(1)$
    • upload(video: str): $O(\log |\texttt{upload()}|)$
    • remove(videoId: int): $O(1)$
    • watch(videoId: int, startMinute: int, endMinute: int): $O(1)$
    • like(videoId: int): $O(1)$
    • dislike(videoId: int): $O(1)$
    • getLikesAndDislikes(videoId: int): $O(1)$
    • getViews(videoId: int): $O(1)$
  • Space: $O(|\texttt{upload()}|)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class VideoSharingPlatform {
 public:
  int upload(string video) {
    const int videoId = getVideoId();
    videoIdToVideo[videoId] = video;
    return videoId;
  }

  void remove(int videoId) {
    if (videoIdToVideo.contains(videoId)) {
      usedIds.push(videoId);
      videoIdToVideo.erase(videoId);
      videoIdToViews.erase(videoId);
      videoIdToLikes.erase(videoId);
      videoIdToDislikes.erase(videoId);
    }
  }

  string watch(int videoId, int startMinute, int endMinute) {
    const auto it = videoIdToVideo.find(videoId);
    if (it == videoIdToVideo.cend())
      return "-1";
    ++videoIdToViews[videoId];
    const string video = it->second;
    const int duration =
        min(endMinute, static_cast<int>(video.length()) - 1) - startMinute + 1;
    return video.substr(startMinute, duration);
  }

  void like(int videoId) {
    if (videoIdToVideo.contains(videoId))
      ++videoIdToLikes[videoId];
  }

  void dislike(int videoId) {
    if (videoIdToVideo.contains(videoId))
      ++videoIdToDislikes[videoId];
  }

  vector<int> getLikesAndDislikes(int videoId) {
    return videoIdToVideo.contains(videoId)
               ? vector<int>{videoIdToLikes[videoId],
                             videoIdToDislikes[videoId]}
               : vector<int>{-1};
  }

  int getViews(int videoId) {
    return videoIdToVideo.contains(videoId) ? videoIdToViews[videoId] : -1;
  }

 private:
  int currVideoId = 0;
  priority_queue<int, vector<int>, greater<>> usedIds;
  unordered_map<int, string> videoIdToVideo;
  unordered_map<int, int> videoIdToViews;
  unordered_map<int, int> videoIdToLikes;
  unordered_map<int, int> videoIdToDislikes;

  int getVideoId() {
    if (usedIds.empty())
      return currVideoId++;
    const int minUsedId = usedIds.top();
    usedIds.pop();
    return minUsedId;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class VideoSharingPlatform {
  public int upload(String video) {
    final int videoId = getVideoId();
    videoIdToVideo.put(videoId, video);
    return videoId;
  }

  public void remove(int videoId) {
    if (videoIdToVideo.containsKey(videoId)) {
      usedIds.offer(videoId);
      videoIdToVideo.remove(videoId);
      videoIdToViews.remove(videoId);
      videoIdToLikes.remove(videoId);
      videoIdToDislikes.remove(videoId);
    }
  }

  public String watch(int videoId, int startMinute, int endMinute) {
    if (!videoIdToVideo.containsKey(videoId))
      return "-1";
    videoIdToViews.merge(videoId, 1, Integer::sum);
    final String video = videoIdToVideo.get(videoId);
    return video.substring(startMinute, Math.min(endMinute + 1, video.length()));
  }

  public void like(int videoId) {
    if (videoIdToVideo.containsKey(videoId))
      videoIdToLikes.merge(videoId, 1, Integer::sum);
  }

  public void dislike(int videoId) {
    if (videoIdToVideo.containsKey(videoId))
      videoIdToDislikes.merge(videoId, 1, Integer::sum);
  }

  public int[] getLikesAndDislikes(int videoId) {
    return videoIdToVideo.containsKey(videoId)
        ? new int[] {videoIdToLikes.getOrDefault(videoId, 0),
                     videoIdToDislikes.getOrDefault(videoId, 0)}
        : new int[] {-1};
  }

  public int getViews(int videoId) {
    return videoIdToVideo.containsKey(videoId) ? videoIdToViews.getOrDefault(videoId, 0) : -1;
  }

  private int currVideoId = 0;
  private Queue<Integer> usedIds = new PriorityQueue<>();
  private Map<Integer, String> videoIdToVideo = new HashMap<>();
  private Map<Integer, Integer> videoIdToViews = new HashMap<>();
  private Map<Integer, Integer> videoIdToLikes = new HashMap<>();
  private Map<Integer, Integer> videoIdToDislikes = new HashMap<>();

  private int getVideoId() {
    if (usedIds.isEmpty())
      return currVideoId++;
    return usedIds.poll();
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class VideoSharingPlatform:
  def __init__(self):
    self.currVideoId = 0
    self.usedIds = []
    self.videoIdToVideo = {}
    self.videoIdToViews = collections.Counter()
    self.videoIdToLikes = collections.Counter()
    self.videoIdToDislikes = collections.Counter()

  def upload(self, video: str) -> int:
    videoId = self._getVideoId()
    self.videoIdToVideo[videoId] = video
    return videoId

  def remove(self, videoId: int) -> None:
    if videoId in self.videoIdToVideo:
      heapq.heappush(self.usedIds, videoId)
      del self.videoIdToVideo[videoId]
      del self.videoIdToViews[videoId]
      del self.videoIdToLikes[videoId]
      del self.videoIdToDislikes[videoId]

  def watch(self, videoId: int, startMinute: int, endMinute: int) -> str:
    if videoId not in self.videoIdToVideo:
      return '-1'
    self.videoIdToViews[videoId] += 1
    video = self.videoIdToVideo[videoId]
    return video[startMinute:min(endMinute + 1, len(video))]

  def like(self, videoId: int) -> None:
    if videoId in self.videoIdToVideo:
      self.videoIdToLikes[videoId] += 1

  def dislike(self, videoId: int) -> None:
    if videoId in self.videoIdToVideo:
      self.videoIdToDislikes[videoId] += 1

  def getLikesAndDislikes(self, videoId: int) -> list[int]:
    if videoId in self.videoIdToVideo:
      return [self.videoIdToLikes[videoId], self.videoIdToDislikes[videoId]]
    return [-1]

  def getViews(self, videoId: int) -> int:
    if videoId in self.videoIdToVideo:
      return self.videoIdToViews[videoId]
    return -1

  def _getVideoId(self) -> int:
    if not self.usedIds:
      self.currVideoId += 1
      return self.currVideoId - 1
    return heapq.heappop(self.usedIds)