← Static tasks

635. Design Log Storage System

leetcode medium

#array#backtracking#csharp#design#leetcode#medium#prefix-sum#string#tree#trie

Task

Вам дается несколько журналов, где каждый журнал содержит уникальный идентификатор и временную метку. Временная метка - это строка, имеющая следующий формат: Год:Месяц:День:Час:Минута:Секунда, например, 2017:01:01:23:59:59. Все домены - десятичные числа с нулевым добавлением. Реализация класса LogSystem: LogSystem() Инициализирует объект LogSystem. void put(int id, string timestamp) Сохраняет заданный журнал (id, timestamp) в вашей системе хранения.

int[] retrieve(string start, string end, string granularity) Возвращает идентификаторы журналов, временные метки которых находятся в диапазоне от start до end включительно. start и end имеют тот же формат, что и timestamp, а granularity означает, насколько точным должен быть диапазон (т. е. с точностью до дня, минуты и т. д.). Например, start = "2017:01:01:23:59:59", end = "2017:01:02:23:59:59", а granularity = "Day" означает, что нам нужно найти журналы в диапазоне от 1 января 2017 года до 2 января 2017 года включительно, а час, минуту и секунду для каждой записи журнала можно игнорировать.

Пример:

Input

["LogSystem", "put", "put", "put", "retrieve", "retrieve"]

[[], [1, "2017:01:01:23:59:59"], [2, "2017:01:01:22:59:59"], [3, "2016:01:01:00:00:00"], ["2016:01:01:01:01:01", "2017:01:01:23:00:00", "Year"], ["2016:01:01:01:01:01", "2017:01:01:23:00:00", "Hour"]]

Output

[null, null, null, null, [3, 2, 1], [2, 1]]

C# solution

matched/original
using System;
using System.Collections.Generic;
public class LogSystem {
    private List<LogEntry> logs;
    public LogSystem() {
        logs = new List<LogEntry>();
    }
    public void Put(int id, string timestamp) {
        logs.Add(new LogEntry(id, timestamp));
    }
    public IList<int> Retrieve(string start, string end, string granularity) {
        int index = GetGranularityIndex(granularity);
        string startPrefix = start.Substring(0, index);
        string endPrefix = end.Substring(0, index);
        List<int> result = new List<int>();
        foreach (var log in logs) {
            string timestampPrefix = log.Timestamp.Substring(0, index);
            if (startPrefix.CompareTo(timestampPrefix) <= 0 && timestampPrefix.CompareTo(endPrefix) <= 0) {
                result.Add(log.Id);
            }
        }
        return result;
    }
    private int GetGranularityIndex(string granularity) {
        switch (granularity) {
            case "Year": return 4;
            case "Month": return 7;
            case "Day": return 10;
            case "Hour": return 13;
            case "Minute": return 16;
            case "Second": return 19;
            default: return 19;
        }
    }
    private class LogEntry {
        public int Id { get; }
        public string Timestamp { get; }
        public LogEntry(int id, string timestamp) {
            Id = id;
            Timestamp = timestamp;
        }
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class LogSystem {
    private List<LogEntry> logs;
    public LogSystem() {
        logs = new List<LogEntry>();
    }
    public void Put(int id, string timestamp) {
        logs.push_back(new LogEntry(id, timestamp));
    }
    public vector<int> Retrieve(string start, string end, string granularity) {
        int index = GetGranularityIndex(granularity);
        string startPrefix = start.Substring(0, index);
        string endPrefix = end.Substring(0, index);
        List<int> result = new List<int>();
        foreach (var log in logs) {
            string timestampPrefix = log.Timestamp.Substring(0, index);
            if (startPrefix.CompareTo(timestampPrefix) <= 0 && timestampPrefix.CompareTo(endPrefix) <= 0) {
                result.push_back(log.Id);
            }
        }
        return result;
    }
    private int GetGranularityIndex(string granularity) {
        switch (granularity) {
            case "Year": return 4;
            case "Month": return 7;
            case "Day": return 10;
            case "Hour": return 13;
            case "Minute": return 16;
            case "Second": return 19;
            default: return 19;
        }
    }
    private class LogEntry {
        public int Id { get; }
        public string Timestamp { get; }
        public LogEntry(int id, string timestamp) {
            Id = id;
            Timestamp = timestamp;
        }
    }
}

Java solution

matched/original
import java.util.*;

public class LogSystem {
    private List<LogEntry> logs;

    public LogSystem() {
        logs = new ArrayList<>();
    }

    public void put(int id, String timestamp) {
        logs.add(new LogEntry(id, timestamp));
    }

    public List<Integer> retrieve(String start, String end, String granularity) {
        int index = getGranularityIndex(granularity);
        start = start.substring(0, index);
        end = end.substring(0, index);
        
        List<Integer> result = new ArrayList<>();
        for (LogEntry log : logs) {
            String timestamp = log.timestamp.substring(0, index);
            if (start.compareTo(timestamp) <= 0 && timestamp.compareTo(end) <= 0) {
                result.add(log.id);
            }
        }
        return result;
    }

    private int getGranularityIndex(String granularity) {
        switch (granularity) {
            case "Year":
                return 4;
            case "Month":
                return 7;
            case "Day":
                return 10;
            case "Hour":
                return 13;
            case "Minute":
                return 16;
            case "Second":
                return 19;
            default:
                return 19;
        }
    }

    private static class LogEntry {
        int id;
        String timestamp;

        LogEntry(int id, String timestamp) {
            this.id = id;
            this.timestamp = timestamp;
        }
    }
}

JavaScript solution

matched/original
class LogSystem {
    constructor() {
        this.logs = [];
        this.granularity = {
            "Year": 4,
            "Month": 7,
            "Day": 10,
            "Hour": 13,
            "Minute": 16,
            "Second": 19
        };
    }

    put(id, timestamp) {
        this.logs.push({ id, timestamp });
    }

    retrieve(start, end, granularity) {
        const length = this.granularity[granularity];
        start = start.slice(0, length);
        end = end.slice(0, length);
        return this.logs.filter(log => {
            const ts = log.timestamp.slice(0, length);
            return start <= ts && ts <= end;
        }).map(log => log.id);
    }
}

Python solution

matched/original
class LogSystem:
    def __init__(self):
        self.logs = []

    def put(self, id: int, timestamp: str) -> None:
        self.logs.append((id, timestamp))

    def retrieve(self, start: str, end: str, granularity: str) -> [int]:
        index = {
            'Year': 4,
            'Month': 7,
            'Day': 10,
            'Hour': 13,
            'Minute': 16,
            'Second': 19
        }[granularity]
        
        start = start[:index]
        end = end[:index]
        
        result = []
        for id, timestamp in self.logs:
            if start <= timestamp[:index] <= end:
                result.append(id)
        return result

Go solution

matched/original
package main

import (
  "strings"
)

type LogSystem struct {
  logs        []Log
  granularity map[string]int
}

type Log struct {
  id        int
  timestamp string
}

func Constructor() LogSystem {
  return LogSystem{
    logs: []Log{},
    granularity: map[string]int{
      "Year":   4,
      "Month":  7,
      "Day":    10,
      "Hour":   13,
      "Minute": 16,
      "Second": 19,
    },
  }
}

func (this *LogSystem) Put(id int, timestamp string) {
  this.logs = append(this.logs, Log{id, timestamp})
}

func (this *LogSystem) Retrieve(start string, end string, granularity string) []int {
  length := this.granularity[granularity]
  start = start[:length]
  end = end[:length]
  var result []int
  for _, log := range this.logs {
    ts := log.timestamp[:length]
    if start <= ts && ts <= end {
      result = append(result, log.id)
    }
  }
  return result
}

Explanation

Algorithm

Инициализация и хранение журналов

Реализуйте метод put, который будет сохранять журнал с заданным id и timestamp в системе хранения.

Формирование диапазона

Реализуйте метод retrieve, который будет формировать диапазон временных меток на основе заданного start, end и granularity.

Фильтрация и возврат результатов

Используйте сформированный диапазон для фильтрации журналов и возврата идентификаторов тех журналов, чьи временные метки попадают в этот диапазон.

😎