новый для, поэтому, пожалуйста, не возражайте против моего способа noob спросить об этом. Я пытаюсь реализовать кэширование LRU с помощью связанного списка, я видел другие реализации здесь, используя linkedHashMap и другие структуры данных, но для этого случая я пытаюсь создать лучшую оптимизированную версию, используя связанные списки, как меня спрашивали во время технической круглый.
Я ограничил размер кэша здесь до 3
И какова будет временная сложность для этой реализации? будет ли он порядка O (N) без учета for-loops, которые просто печатают значения в связанномList?
public class LRU {
public static void main(String[] args) {
LinkedList list = new LinkedList();
int[] feed = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };
for (int i = 0; i < feed.length - 1; i++) {
if (list.size() <= 2) {
list.add(feed[i]);
System.out.println();
System.out.println("Added " + feed[i]);
System.out.println("size of list is " + list.size());
System.out.print("this is list ");
for (int k = 0; k < list.size(); k++) {
System.out.print(" " + list.get(k));
}
}
System.out.println();
if (list.size() >= 3) {
System.out.println();
System.out.println("feed is *" + feed[i + 1] + "*");
Integer value1 = (Integer) list.get(0);
Integer value2 = (Integer) list.get(1);
Integer value3 = (Integer) list.get(2);
if ((feed[i + 1] != value1) || (feed[i + 1] != value2)
|| (feed[i + 1] != value3)) {
list.removeLast();
list.addLast(feed[i + 1]);
list.set(0, value2);
list.set(1, value3);
list.set(2, feed[i + 1]);
}
if (feed[i + 1] == value1) {
list.removeLast();
list.addLast(value1);
list.removeFirst();
list.addFirst(value2);
list.set(1, value3);
}
if (feed[i + 1] == value2) {
list.removeLast();
list.addLast(value2);
list.set(1, value3);
list.removeFirst();
list.addFirst(value1);
}
if (feed[i + 1] == value3) {
list.set(0, value1);
list.set(1, value2);
}
}
System.out.println("Current elements in cache at " + i);
for (int t = 0; t < list.size(); t++) {
System.out.print(" " + list.get(t));
}
System.out.println();
}
System.out.println();
System.out.println("------------------------------");
System.out.println("current elements in cache ");
for (int i = 0; i < list.size(); i++) {
System.out.print(" " + list.get(i));
}
}
}
Прежде всего, вы хотите определить интерфейс. Прямо сейчас я не вижу, как вы должны использовать свой кеш или на самом деле то, что вы делаете. Попробуйте реализовать следующий класс:
class LRUCache {
final int size;
Cache(int size){
this.size = size;
}
void put(String key, Integer value){
//
}
Integer get(String key){
//
}
}
EDIT (ответ на комментарий):
Какова бы ни была проблема, первым шагом является определение интерфейса (с помощью которого я не имею в виду интерфейсы Java, просто то, что сообщает, что происходит). В этом случае попробуйте реализовать это.
class MRU {
final int size;
MRU(int size){
this.size = size;
}
void put(Integer value){
//
}
Set<Integer> mostRecentlyUsed(){
//
}
}
Здесь мой связанный список с LRU-кешем, он не будет передавать судья-ликету, потому что связанный список занимает слишком много времени (вы получите превышение лимита времени).
открытый класс LRUCache {
private Map<Integer, Integer> blocks = new HashMap<Integer,Integer>();
private LinkedList<Integer> bru = new LinkedList<Integer>();
private int capacity;
private int length;
public LRUCache(int capacity) {
this.capacity = capacity;
this.length = 0;
}
public int get(int key) {
Integer value = blocks.get(key);
if (value != null) {
bru.remove(value);
bru.addFirst(value);
return value;
}
return -1;
}
public void set(int key, int value) {
if (blocks.containsKey(key)) {
bru.remove(blocks.get(key));
blocks.put(key, value);
} else {
if (length >= capacity) {
blocks.remove(bru.removeLast());
length--;
}
length++;
blocks.put(key, value);
}
bru.addFirst(value);
}
}
Я бы использовал
LinkedList<Integer> list = new LinkedList<>();
и вместо вашей реализации я бы использовал
if (list.size() >= 3) {
System.out.println();
System.out.println("feed is *" + feed[i + 1] + "*");
// retrieve the next value from the feed
Integer next = feed[i + 1];
if (!list.remove(next)) {
list.removeLast();
}
list.addFirst(next);
}
System.out.println("Current elements in cache at " + i);
В случае, если следующее значение находится в списке, оно удаляется и помещается в качестве первого элемента в списке.
В случае, если следующее значение отсутствует в списке, последний элемент удаляется, а следующее значение ставится как первый элемент в списке.
Когда вы затем просматриваете элементы в списке, например, с помощью indexOf (...), поиск выполняется с самой последней до самой старой записи.