ys memos

Blog

[Rust]LeetCode 1396 Design Underground System


rust

2022/04/24


地下鉄システムのうち,特定の駅間の平均所要時間を求める問題


main.rs
use std::collections::HashMap;

struct User {
  start: String,
  time: i32
}

struct Record {
  sum: i32,
  count: i32,
}

struct UndergroundSystem {
  users: HashMap<i32, User>,
  records: HashMap<String, Record>
}

impl UndergroundSystem {
  fn new() -> Self {
    Self {
      users: HashMap::new(),
      records: HashMap::new()
    }
  }

  fn get_key(&self, start_station: String, end_station: String) -> String {
    let mut key = start_station.clone();
    key.push('-');
    key.push_str(end_station.as_str());
    key
  }

  fn check_in(&mut self, id: i32, station_name: String, t: i32) {
    let user = User {start:station_name.clone(), time:t};
    self.users.insert(id, user);
  }

  fn check_out(&mut self, id: i32, station_name: String, t: i32) {
    let user = self.users.get(&id).unwrap();
    let key = self.get_key(user.start.clone(), station_name);
    let record = self.records.entry(key).or_insert(Record{sum:0,count:0});
    (*record).sum += (t - user.time);
    (*record).count += 1;
  }

  fn get_average_time(&self, start_station: String, end_station: String) -> f64 {
    let key = self.get_key(start_station, end_station);
    let record = self.records.get(&key).unwrap();

    ((*record).sum as f64) / ((*record).count as f64)
  }
}


今回は,HashMap を利用して問題を解く.

use std::collections::HashMap;

ユーザ情報管理用の struct を定義しておく.

名前の通り,startcheckInした駅名を,timecheckInした時間を記録する.

struct User {
  start: String,
  time: i32
}

特定の駅間の所要時間の情報を記録する struct を定義する.

sumには所要時間の合計を,countには利用回数を記録する.

struct Record {
  sum: i32,
  count: i32,
}

システムは,(1)現在のユーザの情報,(2)2駅間の所要時間情報をもつ.

ここで,それらの情報はそれぞれ,User, Recordで定義したものとする.

struct UndergroundSystem {
  users: HashMap<i32, User>,
  records: HashMap<String, Record>
}

システム起動時は何も情報を持たないので,空の HashMap で初期化する.

impl UndergroundSystem {
  fn new() -> Self {
    Self {
      users: HashMap::new(),
      records: HashMap::new()
    }
  }

2駅間の情報を指し示すキーを取得する.

今回は,スタートとエンドの両駅の名前を単純に-でつないだものとする.

  fn get_key(&self, start_station: String, end_station: String) -> String {
    let mut key = start_station.clone();
    key.push('-');
    key.push_str(end_station.as_str());
    key
  }

駅に入場する場合に呼ばれる関数.

usersに各種情報を保存する.

  fn check_in(&mut self, id: i32, station_name: String, t: i32) {
    let user = User {start:station_name.clone(), time:t};
    self.users.insert(id, user);
  }

駅から退場するための関数.

ユーザの入退場駅および入退場時刻から,recordsを更新する.

  fn check_out(&mut self, id: i32, station_name: String, t: i32) {
    let user = self.users.get(&id).unwrap();
    let key = self.get_key(user.start.clone(), station_name);
    let record = self.records.entry(key).or_insert(Record{sum:0,count:0});
    (*record).sum += (t - user.time);
    (*record).count += 1;
  }

2駅間の平均所要時間を返す関数.

recordsに保存されている合計所要時刻とカウントから,平均を求める.

  fn get_average_time(&self, start_station: String, end_station: String) -> f64 {
    let key = self.get_key(start_station, end_station);
    let record = self.records.get(&key).unwrap();

    ((*record).sum as f64) / ((*record).count as f64)
  }
}

だんだん Rust に慣れてきた気がする.特に,StackOverflow よりも公式 Docs のリファレンスから情報をとれるようになってきたという点が嬉しい.


関連タグを探す