165. Design LRU Cache With Time Constraint

Asked in

LRU Cache With Time Constraint
Design an LRUCacheWithTimeConstraint class that implements an LRU cache with a fixed capacity and a time constraint.

The cache stores key-value pairs.

Each key-value pair remains valid only for a fixed number of seconds after it is inserted or updated.

If a key is accessed after its valid time has expired, it must be treated as missing from the cache.

When the cache exceeds its fixed capacity, the least recently used valid key must be removed.

A successful get operation makes that key the most recently used key.

A put operation also makes the inserted or updated key the most recently used key.

Before processing any operation, all expired keys must be considered unavailable.

Class and Method Signatures

LRUCacheWithTimeConstraint(int capacity, int ttlSeconds)
  • Initializes the cache with a fixed maximum capacity.
  • Each key remains valid for exactly ttlSeconds seconds after its latest put operation.
void put(String key, String value, int currentTime)
  • Inserts a new key-value pair into the cache.
  • If the key already exists and is not expired, update its value and refresh its expiry time.
  • If the key already exists but is expired, remove the expired entry first and insert it as a new key.
  • The key becomes the most recently used key after this operation.
String get(String key, int currentTime)
  • Returns the value stored for the key if the key exists and is not expired.
  • Returns "NOT_FOUND" if the key does not exist or has expired.
  • A successful get makes the key the most recently used key.

Expiry Rule

If a key is inserted or updated at time t, then it is valid for all calls where:
currentTime < t + ttlSeconds

The key is expired when:
currentTime >= t + ttlSeconds

LRU Eviction Rule

After removing expired keys, if inserting a new key causes the number of valid keys to become greater than capacity, remove the least recently used valid key.

Recency is updated only by:
  • A successful get operation.
  • A put operation that inserts or updates a key.

Important Notes

  • currentTime is in seconds and is monotonically increasing (non-decreasing) across all methods.
  • If multiple operations happen at the same currentTime, their recency is determined by method call order. A later method call is more recent than an earlier method call.
  • Expired keys must not be returned by get.
  • Expired keys must not count toward cache capacity.
  • Calling get on an expired key removes it from the cache and returns "NOT_FOUND".
  • Calling put on an expired key inserts it again with a new expiry time.
  • The value "NOT_FOUND" is reserved and will not be used as an input value.
  • No parameter value will be null.

Constraints

  • 1 ≤ capacity ≤ 105
  • 1 ≤ ttlSeconds ≤ 106
  • 1 ≤ key.length() ≤ 50
  • 1 ≤ value.length() ≤ 50
  • 0 ≤ currentTime ≤ 109
  • At most 105 method calls will be made.
  • key and value contain only lowercase English letters, uppercase English letters, digits, hyphen, and underscore.
  • value will never be "NOT_FOUND".

Examples

Example 1

LRUCacheWithTimeConstraint cache = new LRUCacheWithTimeConstraint(capacity = 2, ttlSeconds = 5);
cache.put(key = "A", value = "Apple", currentTime = 1);
cache.put(key = "B", value = "Banana", currentTime = 2);
cache.get(key = "A", currentTime = 3) returns "Apple"
cache.put(key = "C", value = "Cherry", currentTime = 4);
cache.get(key = "B", currentTime = 4) returns "NOT_FOUND"

Explanation:
The cache capacity is 2.
Key "A" is accessed at time 3, so it becomes the most recently used key.
When key "C" is inserted at time 4, key "B" is the least recently used valid key, so it is removed.

Example 2

LRUCacheWithTimeConstraint cache = new LRUCacheWithTimeConstraint(capacity = 2, ttlSeconds = 3);
cache.put(key = "A", value = "Apple", currentTime = 10);
cache.get(key = "A", currentTime = 12) returns "Apple"
cache.get(key = "A", currentTime = 13) returns "NOT_FOUND"

Explanation:
Key "A" is inserted at time 10.
Since ttlSeconds = 3, it is valid while currentTime < 13.
At time 13, the key has expired and must return "NOT_FOUND".

Example 3

LRUCacheWithTimeConstraint cache = new LRUCacheWithTimeConstraint(capacity = 2, ttlSeconds = 5);
cache.put(key = "A", value = "Apple", currentTime = 1);
cache.put(key = "B", value = "Banana", currentTime = 2);
cache.put(key = "A", value = "Apricot", currentTime = 4);
cache.get(key = "A", currentTime = 8) returns "Apricot"
cache.get(key = "B", currentTime = 8) returns "NOT_FOUND"
cache.get(key = "A", currentTime = 9) returns "NOT_FOUND"

Explanation:
Key "A" is updated at time 4, so its value becomes "Apricot" and its expiry time is refreshed.
Key "A" remains valid while currentTime < 9.
Key "B" was inserted at time 2, so it expires at time 7.

Example 4

LRUCacheWithTimeConstraint cache = new LRUCacheWithTimeConstraint(capacity = 1, ttlSeconds = 10);
cache.put(key = "A", value = "Apple", currentTime = 1);
cache.put(key = "B", value = "Banana", currentTime = 2);
cache.get(key = "A", currentTime = 3) returns "NOT_FOUND"
cache.get(key = "B", currentTime = 3) returns "Banana"

Explanation:
The cache capacity is 1.
When key "B" is inserted, key "A" is the least recently used valid key and is removed.




Please use Laptop/Desktop or any other large screen to add/edit code.