What's wrong with my LRUCache code - java

I try to solution a question in LeetCode,it's ask to implement a LRUCache.
And when I submit my code, the System told me the result is Wrong Answer.
Because the TestCase is too long ,I can't find the problem in my code.And when I choice "Run code" to sumbit my code,it's correct.
Here is my code
public class LRUCache {
private int capacity;
private int size;
private HashMap<Integer, Node> cache = new HashMap<>();
private Node tail;
private Node head;
public LRUCache(int capacity) {
this.capacity = capacity;
size = 0;
tail = new Node(-1, -1);
head = new Node(-1, -1);
tail.setPrev(head);
head.setNext(tail);
}
public Integer get(int key) {
Integer value = -1;
Node old = cache.get(key);
if (old != null){
//move to tail
Node node = new Node(key, old.getValue());
removeNode(old);
moveToTail(node);
value = node.getValue();
}
return value;
}
public void put(int key, int value) {
Node n = new Node(key, value);
Node old = cache.get(key);
boolean isExist = old != null;
if (isExist){
removeNode(old);
size--;
}
//move to tail
moveToTail(n);
cache.put(key, n);
size++;
//remove node if size upper than capacity
while (capacity < size){
Node rm = head.getNext();
cache.remove(rm.getKey());
removeNode(rm);
size--;
}
}
private void removeNode(Node node){
if (node.getPrev() != head){
node.getPrev().setNext(node.getNext());
node.getNext().setPrev(node.getPrev());
}else {
head.setNext(node.getNext());
node.getNext().setPrev(head);
}
node = null;
}
private void moveToTail(Node node){
node.setPrev(tail.getPrev());
tail.getPrev().setNext(node);
tail.setPrev(node);
node.setNext(tail);
}
private class Node{
private int key;
private int value;
private Node prev;
private Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
this.prev = null;
this.next = null;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}

I guess there is problem in your get and put methods. Every time you are creating new nodes. Ideally it should be the same node moved across the DLL. Also, the node should have a setValue() method for updates.
The following update should work.
public Integer get(int key) {
Integer value = -1;
Node old = cache.get(key);
if (old != null){
//move to tail
/////Node node = new Node(key, old.getValue());
removeNode(old);
moveToTail(old);
value = old.getValue();
}
return value;
}
public void put(int key, int value) {
Node n = null;
n = cache.get(key);
if (n != null){
//Update the value of node and move
n.setValue(value);
removeNode(n);
size--;
}
else {
n = new Node(key, value);
}
//move to tail
moveToTail(n);
cache.put(key, n);
size++;
//remove node if size upper than capacity
while (capacity < size){
Node rm = head.getNext();
cache.remove(rm.getKey());
removeNode(rm);
size--;
}
}
Hope it helps!

Related

How to create a doubly linked list of multiple data types

I am currently writing a program that creates Students and stores them in a doubly linked list based on their natural order (Last name, First name, GPA, then student ID). I am just starting off with generics and how they work so I am a little lost. I believe most of my code is working; the only part I need help with is adding students (who have multiple data types) into my list in my main method in my doubly linked list class. Any help is greatly appreciated! Here is my student, doubly linked list, and node class along with a fragment of the input file I am reading from with the data of each student:
Student class:
public class Student{
long studentID;
String firstName;
String lastName;
float GPA;
public Student(String lastName, String firstName, float GPA, long studentID){
this.lastName = lastName;
this.firstName = firstName;
this.GPA = GPA;
this.studentID = studentID;
}
public int compareTo(Student s){
int result = this.lastName.compareTo(s.lastName);
if(result == 0){
result = this.firstName.compareTo(s.firstName);
if(result == 0){
result = Float.compare(this.GPA, s.GPA);
if(result == 0){
result = Long.compare(this.studentID, s.studentID);
}
}
}
return result;
}
public String toString(){
return this.lastName + ", " + this.firstName +
" GPA: " + this.GPA + " ID: " + this.studentID;
}
}
Node class:
public class Node<T>{
Node<T> previous;
Node<T> next;
Student data;
public Node(Student data){
this(data, null, null);
}
public Node(Student data, Node<T> previous, Node<T> next){
this.data = data;
this.previous = previous;
this.next = next;
}
}
Doubly Linked List class:
import java.io.*;
import java.util.*;
import csci1140.*;
public class DoublyLinkedList<T> implements Iterable<Node>{
private Node root;
private Node tail;
private Node previous;
private class ListIterator implements Iterator<Node>{
Node current = root;
public boolean hasNext(){
return (current != null);
}
public Node next(){
Node answer;
answer = current;
current = current.next;
return answer;
}
}
public Iterator<Node> iterator(){
ListIterator listIterator = new ListIterator();
return listIterator;
}
public void add(T data){
Node<Student> newNode = new Node<Student>(data);
if(root == null){
root = newNode;
tail = root;
return;
}
Node current = root;
for( ; current!= null; current = current.next){
if(newNode.data.compareTo(current.data)<= 0){
break;
}
}
if(previous == null){
previous.next = newNode;
newNode.next = current;
if(current == null){
tail = newNode;
}
} else {
newNode.next = root;
root = newNode;
}
}
public static final void main(String[] args){
FileInputStream fileIn = null;
try{
fileIn = new FileInputStream("student_input.txt");
System.setIn(fileIn);
} catch(FileNotFoundException fnfe){
fnfe.printStackTrace(System.err);
}
//Do work here to create list of students
}
try{
fileIn.close();
} catch(Exception e){}
}
}
Student_input.txt:
1000
Lisa
Licata
2.28
1001
Shelley
Santoro
1.56
1002
Ok
Ota
3.33
1003
Cindi
Caggiano
1.65
Still not completely sure, maybe some variation of this.
Especially this inserts before the first Node that is bigger, and I am still not sure what the generics are for in this case and T needs to be something that extends Student(well it needs the compareTo method):
public void add(T data) {
for(Node<T> current = root; current != null; current = current.next) {
if (data.compareTo(current.data) <= 0) {
current = new Node<>(data,current.previous,current);
if(null == current.previous){
root = current;
}else {
current.previous.next = current;
}
if(null == current.next){
tail = current;
} else {
current.next.previous = current;
}
return;
}
}
tail = new Node<>(data,tail,null);
if(null == tail.previous) root=tail;
}
So your list should maybe look like this(to ensure T has the compareTo method):
public class DoublyLinkedList<T extends Student> implements Iterable<Node<T>> {
...
}
All together(To have Node as a seperate file like you do is better - but for brevity I put it into the list):
public class DoublyLinkedList<T extends Student> implements Iterable<Node<T>> {
public static class Node<S> {
Node<S> previous;
Node<S> next;
S data;
public Node(S data) {
this(data, null, null);
}
public Node(S data, Node<S> previous, Node<S> next) {
this.data = data;
this.previous = previous;
this.next = next;
}
}
private Node<T> root = null;
private Node<T> tail = null;
private class ListIterator implements Iterator<Node<T>> {
Node<T> current = root;
#Override
public boolean hasNext() {
return (current != null);
}
#Override
public Node<T> next() {
Node<T> answer;
answer = current;
current = current.next;
return answer;
}
}
#Override
public Iterator<Node<T>> iterator() {
ListIterator listIterator = new ListIterator();
return listIterator;
}
public void add(T data) {
for(Node<T> current = root; current != null; current = current.next) {
if (data.compareTo(current.data) <= 0) {
current = new Node<>(data,current.previous,current);
if(null == current.previous){
root = current;
}else {
current.previous.next = current;
}
if(null == current.next){
tail = current;
} else {
current.next.previous = current;
}
return;
}
}
tail = new Node<>(data,tail,null);
if(null == tail.previous) root=tail;
}
}

NPE when deleting a node at a given position in linked list

Node
private Object data;
private Node link;
private Node next;
private Node prev;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getLink() {
return link;
}
public void setLink(Node link) {
this.link = link;
}
public Node(Object data) {
this.data = data;
this.link = null;
}
public Node getNextNode() {
return next;
}
public Node getPrevNode() {
return prev;
}
public void setNextNode(Node n) {
next = n;
}
public void setPrevNode(Node n) {
prev = n;
}
Item
private int id;
private String name;
private String type;
private double price;
public Item(int id, String name, String type, double price) {
this.id = id;
this.name = name;
this.type = type;
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public double getPrice() {
return price;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setType(String type) {
this.type = type;
}
public void setPrice(double price) {
this.price = price;
}
#Override
public String toString() {
return "Item: " + "ID: " + id + ", Name: " + name + ", Type: " + type + ", Price: " + price;
}
LinkedList
private Node head; // first node in the linked list
private int count;
public int getCount() {
return count;
}
public Node getHead() {
return head;
}
public LinkedList() {
head = null; // creates an empty linked list
count = 0;
}
public void addFront(int n) {
Node newNode = new Node(n);
newNode.setLink(head);
head = newNode;
count++;
}
public void deleteFront() {
if (count > 0) {
head = head.getLink();
count--;
}
}
public void AddItemToFront(Item p) {
Node newNode = new Node(p);
newNode.setLink(head);
head = newNode;
count++;
}
public void DisplayItems() {
Node temp = head;
while(temp != null) {
System.out.println(temp.getData());
temp = temp.getLink();
}
}
public void RemoveItemAtPosition(int n) {
if(n == 1) {
Node x = head;
head = x.getLink();
count--;
}
else if (n > count || n < 0) {
System.out.println("The index you entered is out of bound.");
}
else {
Node x = head;
for (int i = 1; i < n; i++) {
x = x.getNextNode();
}
Node temp = x;
x = temp.getPrevNode();
x.setNextNode(temp.getNextNode());
temp = null;
count--;
}
}
I'm trying to remove a Node at a position given integer n.
I tried researching on SO before posting here and the above is the code that i came out with. However, the code returned me an error saying >java.lang.NullPointerException at LinkedList.java:74 at main:35
The Node is actually an object that is being added to the LinkedList
I checked your code I see that you have some bugs.
your mistakes are:
1 -you use linked object.
2- try to access previous and next without initialization.
3- you only care on the next node.
I removed link form Node class and I do some changes into LinkedList:
public class LinkedList {
private Node head; // first node in the linked list
private int count;
public int getCount() {
return count;
}
public Node getHead() {
return head;
}
public LinkedList() {
head = null; // creates an empty linked list
count = 0;
}
public void addFront(int n) {
Node newNode = new Node(n);
if (head == null) {
head = newNode;
} else {
Node node = head;
head = newNode;
head.setNextNode(node);
node.setPrevNode(head);
}
count++;
}
public void deleteFront() {
if (count > 0) {
head = head.getNextNode();
head.setPrevNode(null);
count--;
}
}
public void AddItemToFront(Item p) {
Node newNode = new Node(p);
if (head == null) {
head = newNode;
} else {
Node node = head;
head = newNode;
head.setNextNode(node);
node.setPrevNode(head);
}
count++;
}
public void DisplayItems() {
Node temp = head;
while (temp != null) {
System.out.println(temp.getData());
temp = temp.getNextNode();
}
}
public void RemoveItemAtPosition(int n) {
if (n == 1) {
deleteFront();
} else if (n > count || n < 0) {
System.out.println("The index you entered is out of bound.");
} else {
Node x = head;
for (int i = 1; i < n; i++) {
x = x.getNextNode();
}
Node temp = x;
temp.getPrevNode().setNextNode(temp.getNextNode());
temp.getNextNode().setPrevNode(temp.getPrevNode());
temp = null;
count--;
}
}
}
When checking the provided source code, in the function AddItemToFront(Item p) only the linked-list is managed with newNode.setLink(head);. Both Node next; and Node prev; are never initialized and never used before in the function removeItemAtPosition(int n).
Warning: your Linked-List is managed on reverse (due to the function void AddItemToFront(Item p)).
A simple way to solve your problem should to use only Node link; also in the function removeItemAtPosition(int n).
Step 1 - in RemoveItemAtPosition(int n), modify the search of the nth Node in the for-loop
Node x = head;
for (int i = 1; i < n; i++) {
x = x.getLink(); // Use Node link
}
Instead of
Node x = head;
for (int i = 1; i < n; i++) {
x = x.getNextNode();
}
Step 2 - in RemoveItemAtPosition(int n), connect the next node link to the node before
Node temp = x.getLink();
x.setLink(temp.getLink());
count--;
Instead of
Node temp = x;
x = temp.getPrevNode();
x.setNextNode(temp.getNextNode());
temp = null;
count--;

How to sort a linked list in alphabetical order using Java?

I am doing an library inventory system, so I was supposed to sort the name inside the Node into alphabetical order. I have bookname, author, isbn number, number of copies and genre, all these information I store inside a class.
I do wrote the code for it to sort alphabetically, but it didn't work.
Could someone tell me what's wrong in my code?
Here is my Linked List class contain insert and display method:
public class LinkedList
{
Node node = new Node();
static Node head;
public LinkedList()
{
head=null;
}
public Node getHead()
{
return head;
}
public static void addNode(Data data)
{
Node newNode = new Node(data, head);
if (head == null) {
head = newNode;
newNode.setNext(null);
} else {
Node next = head;
Node prev = next;
do {
if (data.name.compareTo(next.data.name) < 0) {
break;
}
prev = next;
next = next.getNext();
} while (next != null);
newNode.setNext(next);
if (data.name.compareTo(next.data.name) < 0) {
head = newNode;
} else prev.setNext(newNode);
}
}
public static String displayNode()
{
Node current = head;
String output = "";
while(current != null){
output+=current.data.toString();
current = current.next;
}
return output;
}
Here is my Node class:
public class Node
{
Data data;
Node next;
public Node()
{
next = null;
}
Node(Data data, Node next)
{
this.data = data;
this.next = next;
}
public Object getData()
{
return data;
}
public Node getNext()
{
return next;
}
public void setNext(Node next)
{
this.next=next;
}
}
Here is my Data class:
public class Data {
LinkedList list;
String name;
String author;
int isbn;
int number;
String genre;
public Data(String name, String author, int isbn, int number, String genre)
{
this.name = name;
this.author = author;
this.isbn = isbn;
this.number = number;
this.genre = genre;
}
public String toString()
{
return("Book Name: "+name+"\nAuthor: "+author+"\nISBN Number: "+isbn+"\nNumber of Copies: "+number+"\nGenre: "+genre+"\n\n");
}
public String getName()
{
return name;
}
Here is my Iterator class which I used to display the list:
public class DisplayIterator
{
LinkedList list;
static Node current;
static Node newNode;
DisplayIterator(Node newNode)
{
this.newNode = newNode;
current = list.head;
}
public static boolean hasNext()
{
if(current == null){
return false;
}
else if (current.next == null){
return false;
}
return true;
}
public static Node next()
{
if(hasNext()){
current = current.next;
}
return current;
}
public static void remove(){
throw new UnsupportedOperationException("It is read-only.");
}
}
Thank you.
The following code implements an order based insertion into a linked list. This of course assumes that the list is already sorted. It is safe to make this assumption because the only way in your interface to add nodes to a linked list is via this method.
public static void addNode(Data data) {
Node newNode = new Node(data, head);
if (head == null) {
head = newNode;
return;
}
Node current = head;
while (current.next != null && data.name.compareTo(current.data.name) >= 0) {
current = current.next;
}
if (current == head && data.name.compareTo(current.data.name) < 0) {
newNode.next = head;
head = newNode;
}
else {
newNode.next = current.next;
current.next = newNode;
}
JOptionPane.showMessageDialog(null,"Book Information has been added to the inventory.");
}
I assume, your Node is not the one from java util LinkedList, right? Can you provide the implementation of it? Why does its constructor the head ?
You insert your new element at the begin and try to traverse forward. And at the end of your loop in your current is the first greater and previous the last smaller. Until now correct.
But afterwards, you never use the Previous, and sets the new element to your. You nead to insert it between previous and current. Something like that:
if (previous == null)
head = newData;
else
previous.next = newData;
newData.next = current;
Java has a rich library for sorting for any collection of data
java.util.Collections.sort(YOURLIST_valiable)

Sort Linkedlist with Comparator and Generics java

I'm trying to sort a linkedlist with generics but I'm having trouble with some casting issues. The code is throwing Bus can't be cast to Node. I know the problem is in the comparator (where I casted to Bus) but otherwise I don't know how could I call to the methods defined in Bus (irrelevant whether is Bus or another Object, just testing with a random one) . I've been researching the internet but couldn't find a solution. Here is the code:
/**
* Swaps the current node's element with the previous one
*/
public void swap(){
Object previous = getCurrent().getElement();
Object current = next().getElement();
getCurrent().setElement(previous);
previous().setElement(current);
}
public AbstractList<T> orderBy(Comparator<Node<T>> comparator){
setCurrent(getFirst());
Node<T> aux;
Node<T> current;
boolean check = true;
while (check){
check = false;
aux = getFirst();
current = getFirst().getNext();
while(hasNext()) {
if (comparator.compare(aux, current) > 0) {
check = true;
swap();
}
aux = current;
current = current.getNext();
}
}
return this;
}
The comparator:
import java.util.Comparator;
public class InternComparator implements Comparator<Node<Bus>>{
#Override
public int compare(Node<Bus> o1, Node<Bus> o2) {
return ((Bus)o1.getElement()).getIntern() - ((Bus)o2.getElement()).getIntern();
} //getIntern() returns an Integer
AbstractList (given by the professor):
import java.util.NoSuchElementException;
public class AbstractList<T> {
private Node<T> first;
private Node<T> current;
private Node<T> last;
private int size = 0;
public boolean hasNext(){
return current != last;
}
public boolean hasPrevious(){
return current != first;
}
public Node getCurrent(){
return current;
}
public void setCurrent(Node<T> current) {
this.current = current;
}
public int size(){
return size;
}
public boolean isEmpty(){
return first == last || first == null;
}
public void add(T t){
Node<T> a = new Node<T>(t);
if(first == null){
first = a;
}
if(last == null && first != null){
last = a;
last.setPrevious(first);
first.setNext(last);
}
Node<T> aux = last;
last.setNext(a);
last = a;
last.setPrevious(aux);
current = last;
size++;
}
public Node next(){
if(!hasNext()){
throw new RuntimeException("No elements available next.");
}
current = current.getNext();
return current;
}
public Node previous(){
if(!hasPrevious()){
throw new RuntimeException("No elements available previous.");
}
current = current.getPrevious();
return current;
}
public Node getFirst(){
return first;
}
public Node getLast(){
return last;
}
public void setFirst(Node<T> first){
this.first = first;
}
public void setLast(Node<T> last) {
this.last = last;
}
public void remove(T t){
current = first;
boolean removed = false;
while (hasNext()) {
if (current.getElement() == t || current.getElement().equals(t)) {
if(current != last && current != first) {
current.getNext().setPrevious(current.getPrevious());
current.getPrevious().setNext(current.getNext());
} else if(current == first){
current.getNext().setPrevious(null);
} else if(current == last){
current.getPrevious().setNext(null);
}
removed = true;
return;
}
current = next();
}
if(removed){
size--;
} else {
throw new NoSuchElementException("No such element on the list.");
}
}
public Node goTo(int pos){
if(pos > size){
throw new ArrayIndexOutOfBoundsException("Inexistent Position");
}
current = first;
for(int i = 0; i < pos; i++){
current = next();
}
return current;
}
public void insertAfter(T t){
Node<T> aux = new Node<>(t);
if(current != last) {
Node<T> next = current.getNext();
Node<T> previous = current;
current.getNext().setPrevious(aux);
current.setNext(aux);
aux.setNext(next);
aux.setPrevious(previous);
} else {
current.setNext(aux);
aux.setPrevious(current);
last = aux;
}
size++;
}
public void insertPrevious(T t){
Node<T> aux = new Node<>(t);
if(current != first) {
Node<T> previous = current.getPrevious();
Node<T> next = current;
current.getPrevious().setNext(aux);
current.setPrevious(aux);
aux.setNext(next);
aux.setPrevious(previous);
} else {
Node<T> aux1 = current;
current.setPrevious(aux);
first = aux;
first.setNext(aux1);
}
size++;
}
#Override
public String toString() {
String result = "";
current = first;
while(hasNext()) {
result += current.getElement() + "";
next();
}
return result;
}
}
class Node<T> {
private Object element;
private Node<T> prev;
private Node<T> next;
public Node(T element){
this.element = element;
}
public Node(T element, Node next){
this.element = element;
this.next = next;
}
public Node<T> getNext() {
return next;
}
public Node<T> getPrevious() {
return prev;
}
public Object getElement() {
return element;
}
public void setNext(Node<T> next) {
this.next = next;
}
public void setPrevious(Node<T> prev) {
this.prev = prev;
}
public void setElement(Object element) {
this.element = element;
}
}
Think again: your object is of type Node<Bus>; and you are wondering why the cast to Bus fails?
Or lets rephrase: do you assume that a Bus<People> represents a human being?
If you have a container, then you have to retrieve the contained value; and that can't be achieved by casting the container!
Or, to keep using strange pictures: you don't get an egg out of the box by declaring the box to be an egg. You open the box, and fetch the egg.

Use a linked list to implement a Priority Queue

I have implemented a priority queue using a linked list. In this priority queue the smallest int value has the highest value and therefore by calling the remove method the smallest method will be removed.
Code for Node Class
public class Node {
public int iData;
public Node next;
public Node(int x) {
iData = x;
}
public void displayNode() {
System.out.println(iData + " ");
}
}
Code for Link List
public class LinkList {
private Node first;
public LinkList() {
first = null;
}
public boolean isEmpty() {
return first == null;
}
public void insert(int x) {
Node newNode = new Node(x);
Node previous = null;
Node current = first;
while (current != null && x < current.iData) {
previous = current;
current = current.next;
}
if (previous == null) {
newNode.next = first;
first = newNode;
}
else {
previous.next = newNode;
newNode.next = current;
}
}
public Node remove() {
Node previous = null;
Node current = first;
Node temp = current;
while (current.next != null) {
previous = current;
current = current.next;
}
previous.next = null;
return temp;
}
public void display() {
Node current = first;
while (current != null) {
current.displayNode();
current = current.next;
}
System.out.println(" ");
}
}
Code for Priority Queue
public class PriorityQ {
private LinkList list;
public PriorityQ() {
list = new LinkList();
}
public void insert(int x) {
list.insert(x);
}
public void remove() {
list.remove();
}
public void displayList() {
System.out.println("Largest Value to Smallest");
list.display();
}
}
It is working fine at the moment, however i am not sure if my remove method in the link list class is the best way to go about removing elements. So i am looking for suggestions.
remove() is supposed to remove the first element from the list, right? Why do you loop anything for that?
Since your list is singly-linked (only pointing to next elements in the Node) all you need to do is:
Store the first in a temporary variable (if it's != null)
Then update first to be pointing to the 2nd item in the list
(first.next if != null)
Then return the temporary variable.
This can be implemented by having single pointer to first node and maintaining order by storing the smallest element to the first node.
public class LinkedListBasedOrderedMinPQ<T extends Comparable<T>> implements PriorityQueue<T> {
private Node<T> head;
private int size;
//Maintains an ordered linked list with the min element as the head
#Override
public void insert(T item) {
Node<T> node = head;
head = insert(node, item);
}
private Node<T> insert(Node<T> node, T item) {
Node<T> newNode = createNewNode(item);
if(null == node) {
return newNode;
}
if(node.data.compareTo(item) > 0) {
newNode.next = node;
node = newNode;
} else {
node.next = insert(node.next, item);
}
return node;
}
private Node<T> createNewNode(T item) {
size++;
return new Node<T>(item);
}
#Override
public T remove() {
if(null == head) {
return null;
}
T data = head.data;
head = head.next;
size--;
return data;
}
#Override
public int size() {
return size;
}
private static class Node<T> {
private final T data;
private Node<T> next;
public Node(T data) {
this.data = data;
}
#Override
public String toString() {
return "Node [data=" + data + ", next=" + next + "]";
}
}
}

Categories