Skip to main content
Back to problems
#1500
Medium Algorithms

Design a file sharing system

Hash Table Design Sorting Heap (Priority Queue) Data Stream
41.7% acceptance
Mar 31, 2026
53
132
FileSharing design problem - implementation in test file

Solution

Rust
Time O(n log n)
Space O(n)
LeetCode
solution.rs
use std::cmp::Reverse;
use std::collections::{BTreeSet, BinaryHeap, HashMap, HashSet};

struct FileSharing {
  next_id: i32,
  available_ids: BinaryHeap<Reverse<i32>>,
  user_chunks: HashMap<i32, HashSet<i32>>,
  chunk_users: HashMap<i32, BTreeSet<i32>>,
}


/** 
 * `&self` means the method takes an immutable reference.
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl FileSharing {

  fn new(m: i32) -> Self {
    let _ = m;
    Self {
      next_id: 1,
      available_ids: BinaryHeap::new(),
      user_chunks: HashMap::new(),
      chunk_users: HashMap::new(),
    }
  }
  
  fn join(&mut self, owned_chunks: Vec<i32>) -> i32 {
    let user_id = self
      .available_ids
      .pop()
      .map(|Reverse(id)| id)
      .unwrap_or_else(|| {
        let id = self.next_id;
        self.next_id += 1;
        id
      });

    let chunks: HashSet<i32> = owned_chunks.into_iter().collect();
    for &chunk_id in &chunks {
      self.chunk_users.entry(chunk_id).or_default().insert(user_id);
    }
    self.user_chunks.insert(user_id, chunks);

    user_id
  }
  
  fn leave(&mut self, user_id: i32) {
    if let Some(chunks) = self.user_chunks.remove(&user_id) {
      for chunk_id in chunks {
        if let Some(owners) = self.chunk_users.get_mut(&chunk_id) {
          owners.remove(&user_id);
        }
      }
      self.available_ids.push(Reverse(user_id));
    }
  }
  
  fn request(&mut self, user_id: i32, chunk_id: i32) -> Vec<i32> {
    let owners: Vec<i32> = self
      .chunk_users
      .get(&chunk_id)
      .map(|users| users.iter().copied().collect())
      .unwrap_or_default();

    if !owners.is_empty() {
      self.user_chunks.entry(user_id).or_default().insert(chunk_id);
      self.chunk_users.entry(chunk_id).or_default().insert(user_id);
    }

    owners
  }
}

/**
 * Your FileSharing object will be instantiated and called as such:
 * let obj = FileSharing::new(m);
 * let ret_1: i32 = obj.join(ownedChunks);
 * obj.leave(userID);
 * let ret_3: Vec<i32> = obj.request(userID, chunkID);
 */
const _: () = ();