Description
The solution claims it is O(1)
yet it is O(log(N))
due to the PriorityQueue offer/poll complexity. And really would need to be O(N)
because to update the lastUsed
time it would need to use remove(item); offer(item)
and that is O(N)
complexity on remove(item)
The advanced LRU has a bug:
fun get(key: String): Int? {
val item = map[key]
return if (item == null || item.expiryTime < getSystemTimeForExpiry()) {
null
} else {
item.lastUsed = System.currentTimeMillis()
item.value
}
}
You cannot mutate the value used for calculating priority for the PriorityQueue and expect that the order will change. The item must be removed and added back to the PriorityQueue after this mutation.
Other bug in the description vs. solution, considering CacheItem
method compareTo
override fun compareTo(other: CacheItem) = when {
expiryTime != other.expiryTime -> expiryTime.compareTo(other.expiryTime)
priority != other.priority -> priority.compareTo(other.priority)
else -> lastUsed.compareTo(other.lastUsed)
}
The question description says:
If there are no items past their validity, identify the items with the lowest priority rating and from these, remove the item that was least recently accessed or used.
So that would mean you would need a second PriorityQueue ordered by priority rating + last used
, otherwise you are removing within a combined sort order of expiry time + priority instead of just by priority. The above sort helps to be smart within an expiry time window for times, but those are less likely as expiry times will vary by nanoseconds/milliseconds due to timing of inserts.
So the current implementation orders by more than the spec requires (for expiry time with secondary sort orders), and does not handle priority ordering correctly.