Given a class LinkedList
public class LinkedList {
public Node head = null;
public class Node {
public int value;
public Node next;
}
}
I would like to add a method public int count(int value) that counts the amount of times a number occurs in a list.
I tried the following but it doesn't always work and I'm not sure what I am doing wrong.
public int count(int value) {
int counter = 0;
while(head != null) {
Node tmp = head.next;
while(tmp != null) {
if(head.value == value) {
counter++;
}
tmp = tmp.next;
}
head = head.next;
}
return counter;
}
This method works for 1 4 3 4 4 5, int value = 4 (which returns 3, as it should)
but for 1 2 3 4 4 5, int value = 4, it returns 1.
The simplest approach is: Iterate through the list and increase count for each node that contains 'value'. Since there were several problems in your code, I tried to explain the reason for each line with comments.
public int count(int value) {
int count = 0;
// 'tmp' is the node we are currently processing.
// Starting at the head...
Node tmp = head;
// while we not reached the end of the list
while(tmp != null) {
// if the node has the same value we are searching for
if(tmp.value == value) {
// increase count since we found the value
count++;
}
// Go to the next node (null if we reached the end of the list).
tmp = tmp.next;
}
return count;
}
Try this:
public int count(int value) {
int counter = 0;
Node tmp = head;
while (tmp != null) {
if(tmp.value == value) { // this line contained your biggest mistake
counter++;
}
tmp = tmp.next;
}
return counter;
}
You were not using value parameter at all in your method.
I would suggest you improve your Java learning through the use of an IDE that might give you hints of problems in your code. In this case, the lack of usage of value parameter in your method implementation.
I would suggest: IntelliJ IDEA, Eclipse or Visual Studio code. I am sure there are many more but these are the ones that I know.
This is a small example of what I mean:
Here is the recursive-approach of your problem:
int count(int value){
/* dummy node of your head */
LinkedList temp = this.head;
return count(temp, value);
}
private int count(LinkedList temp, int value){
int counter = 0;
if(temp == null){
return 0;
}
/* increment counter, when value is matched */
if(temp.value == value){
counter += 1;
}
counter += count(temp.next, value);
/* return the final result at the end */
return counter;
}
Related
I would like to write a method public boolean containsArray(int[] arr) which returns true if all the elements of the array are in the list, otherwise it returns false.
I would like to only use the LinkedList class below.
public class LinkedList {
public Node head = null;
public class Node {
public int value;
public Node next;
Node(int value, Node next) {
this.value = value
this.next = next;
}
}
}
So far this is the code I have:
public boolean containsArray(int[] arr) {
Node tmp = head;
while(tmp.next != null) {
for(int i = 0; i < arr.length; i++) {
if(tmp.value == arr[i] {
tmp = tmp.next;
} else {
return false;
}
}
}
return true;
}
My idea is to iterate over the list while comparing the list values to the array elements but I am not sure how to implement this properly.
You should approach this in the other direction. First iterate each value of the array, and for each value look in the linked list to find it.
Also, your while condition is not entirely correct: for instance, if head is null, the while condition will trigger an exception. You should exit the loop when tmp is null, not yet when tmp.next is null.
public boolean containsArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int value = arr[i];
Node tmp = head;
while (true) {
if (tmp == null) {
return false;
}
if (tmp.value == value) {
break;
}
tmp = tmp.next;
}
}
return true;
}
I am trying to do a Leaderboard for a game by using a Sorted Linked List. I was able to do so by sorting the point in descending order which mean higher point to lower point. Moreover, I will also need to put player name together with the point. The problem comes here. The SLL(Sorted Linked List) I implemented is an Integer data type, it works perfectly with the Integer data type as it sorted the numbers.
SortedListInterface<Integer> Player = new LeaderboardSortedLinkedList<Integer>();
But when I trying to put the player name which used String, it won't be able to do so because the point data type will need to follow the player name's data type.
Below are the codes of the driver class:
public class testLeaderboard {
public static void main(String[] args) {
SortedListInterface<Integer> Player = new LeaderboardSortedLinkedList<Integer>();
Player.add(1000000);
Player.add(500000);
Player.add(250000);
Player.add(125000);
Player.add(64000);
Player.add(32000);
Player.add(16000);
Player.add(8000);
Player.add(4000);
Player.add(2000);
Player.add(1000);
Player.add(500);
Player.add(300);
Player.add(200);
Player.add(100);
System.out.printf("=================================\n"
+ " Leaderboard\n"
+"=================================\n");
for(int i=0; i< Player.size();i++){
System.out.printf("%3d. %s\n",(i+1), Player.get(i+1));
}
}
}
Here is the Entity class
public class Player {
private String name;
private int prize;
public Player(String name, int prize) {
this.name = name;
this.prize = prize;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrize() {
return prize;
}
public void setPrize(int prize) {
this.prize = prize;
}
#Override
public String toString() {
return "Player{" + "name=" + name + ", prize=" + prize + '}';
}
}
Here's the custom Sorted Lineked List
public class LeaderboardSortedLinkedList<T extends Comparable<T>> implements SortedListInterface<T> {
private Node firstNode;
private int length;
public LeaderboardSortedLinkedList() {
firstNode = null;
length = 0;
}
public boolean add(T newEntry) {
Node newNode = new Node(newEntry);
Node nodeBefore = null;
Node currentNode = firstNode;
while (currentNode != null && newEntry.compareTo(currentNode.data) < 0) {
nodeBefore = currentNode;
currentNode = currentNode.next;
}
if (isEmpty() || (nodeBefore == null)) { // CASE 1: add at beginning
newNode.next = firstNode;
firstNode = newNode;
} else { // CASE 2: add in the middle or at the end, i.e. after nodeBefore
newNode.next = currentNode;
nodeBefore.next = newNode;
}
length++;
return true;
}
public boolean contains(T anEntry) {
boolean found = false;
Node tempNode = firstNode;
int pos = 1;
while (!found && (tempNode != null)) {
if (anEntry.compareTo(tempNode.data) <= 0) {
found = true;
} else {
tempNode = tempNode.next;
pos++;
}
}
if (tempNode != null && tempNode.data.equals(anEntry)) {
return true;
} else {
return false;
}
}
public int size(){
int count = 0;
//Node current will point to head
Node current = firstNode;
while(current != null) {
//Increment the count by 1 for each node
count++;
current = current.next;
}
return count;
}
public T get(int position){
T result = null;
if ((position >= 1) && (position <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < position - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
public final void clear() {
firstNode = null;
length = 0;
}
public int getLength() {
return length;
}
public boolean isEmpty() {
return (length == 0);
}
public String toString() {
String outputStr = "";
Node currentNode = firstNode;
while (currentNode != null) {
outputStr += currentNode.data + "\n";;
currentNode = currentNode.next;
}
return outputStr;
}
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
private Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
}
And the results is here
=================================
Leaderboard
=================================
1. 1000000
2. 500000
3. 250000
4. 125000
5. 64000
6. 32000
7. 16000
8. 8000
9. 4000
10. 2000
11. 1000
12. 500
13. 300
14. 200
15. 100
Here's my testing on the point with string data type because I can't think a way to use player name and point with 2 different data types at the same time in my custom ADT.
public class testLeaderboard {
public static void main(String[] args) {
SortedListInterface<String> Player = new LeaderboardSortedLinkedList<String>()
Player.add("1000000");
Player.add("500000");
Player.add("250000");
Player.add("125000");
Player.add("64000");
Player.add("32000");
Player.add("16000");
Player.add("8000");
Player.add("4000");
Player.add("2000");
Player.add("1000");
Player.add("500");
Player.add("300");
Player.add("200");
Player.add("100");
System.out.println(Player);
}
And here's the result that it compare the first letter of the string.
8000
64000
500000
500
4000
32000
300
250000
2000
200
16000
125000
1000000
1000
100
Is there anyway to use both String and Integer in one ADT because if i couldn't do so, I won't be able sort the point. I'm so sorry for the long question. I am very new to data structures and algorithms so I really need some help on this. Much appreciate.
To keep the points and names together, you need to add Player objects into the list as they are, not just their points or their names:
SortedListInterface<Player> players = new LeaderboardSortedLinkedList<>();
players.add(new Player("Alpha", 1000000));
players.add(new Player("Beta", 500000));
players.add(new Player("Gamma", 250000));
For this to work, you will need to be able to compare Player objects by their point numbers. You do that by implementing the Comparable interface and adding a compareTo method.
You'll also want to add a toString() method, so that you can print a Player object.
public class Player implements Comparable<Player> {
private String name;
private int prize;
#Override
public int compareTo(Player other) {
return Integer.compare(this.prize, other.prize);
}
#Override
public String toString() {
return String.format("name='%s' prize=%d", name, prize);
}
}
Thank You for helping me I successfully get the output I want. But got a little problem which is this
=================================
Leaderboard
=================================
1. name='Alpha' prize=1000000
2. name='Beta' prize=500000
3. name='Gamma' prize=250000
BUILD SUCCESSFUL (total time: 1 second)
It print the output at this way [name="Alpha"]. Im not sure what is the problem but i guess it's my System.out.print code.
System.out.printf("%3d. %s\n",(i+1), players.get(i+1));
and here's my .get() function.
public T get(int position){
T result = null;
if ((position >= 1) && (position <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < position - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
How we can convert binary to decimal using single linked list and recursive method in java? :-s
Ex:
Input: 1->0->0->NULL
Output: 4
I can think of two ways to solve it:
1- If length of list is known:
// To find length of list
public int length(Node head) {
int count = 0;
while(head != null) {
count++;
head = head.next;
}
return count;
}
public static int convertWhenLengthIsKnown(Node head, int len) {
int sum = 0;
if(head.next != null) {
sum = convertWhenLengthIsKnown(head.next, len-1);
}
return sum + head.data * (int)Math.pow(2,len);
}
// Call this function as below:
convertWhenLengthIsKnown(head, length(head)-1);
If we don't want to calculate length, then we can have a sum variable which is globally accessible,
private static int sum = 0;
public static int convert(Node head,int i) {
if(head.next != null) {
i = convert(head.next, i);
}
sum += head.data * (int)Math.pow(2,i);
return i+1;
}
// Call this function as below:
convert(head,0);
Below is the Node class:
class Node {
int data;
Node next;
Node(int data) {
this.data = data;
}
}
Hope It helps you.
It's a bit tricky recursively because you need to scale "earlier" values depending on the list length, simplest way seems to be to hand down the result "so far" via an additional parameter.
class Node {
int value;
Node next;
int toDecimal(int resultSoFar) {
int resultSoFar = 2 * resultSoFar + value;
return next == null ? resultSoFar : toDecimal(resultSoFar);
}
int toDecimal() {
toDecimal(0);
}
}
Try this (Without the null at the end of the list) :
public Integer binToDec(LinkedList<Integer> list){
Double size = (double) list.size();
if(size == 0D) return 0;
Integer number = list.getFirst();
list.removeFirst();
if(number != 0) return binToDec(list) + number*new Double(Math.pow(2D, size - 1)).intValue();
else return binToDec(list);
}
Be aware that it will clear the list.
As you did not tell anything about your linked list, I assume it's similar to the Node class from pbajpai21.
Without knowing the length of the chain you could with each level shift the value one position to the left.
the class for each node in the list
class Node {
int digit;
Node child;
Node(int data) {
this.digit = data;
}
public int getDigit() {
return digit;
}
public void setChild(Node child) {
this.child = child;
}
public Node getChild() {
return child;
}
}
the class for demonstration
public class Bits {
public static void main(String[] args) {
int[] ints = new int[] {1, 0, 1, 0, 1, 0};
Node parent = new Node(ints[0]);
Node root = parent;
for (int i = 1; i < ints.length; i++) {
Node child = new Node(ints[i]);
parent.setChild(child);
parent = child;
}
long value = computeValue(0, root);
System.out.println();
System.out.println("value = " + value);
}
private static long computeValue(long parentValue, Node node) {
if (node == null) {
return parentValue;
}
// only to print the current digit
System.out.print(node.getDigit());
long value = (parentValue << 1) + node.getDigit();
return computeValue(value, node.getChild());
}
}
output
101010
value = 42
I'm working on a linked-list program, which allows me to loop over the list only once, and I can't copy the elements of the list to another data structure.
Suppose that the list is not empty (has at least one node) and the next of the last node is null.
The following method return the element at the index (2n/3) of a list of length n.
for example if n=1 or n=2 it returns the first element
if n=3 or n=4 it returns the second element.
I thought of keeping a temporary node that gets the next node if the number (2n/3) is an integer.
Is there a better way to do this?
public class LinkedListNode {
private int value;
private LinkedListNode next;
public LinkedListNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public LinkedListNode getNext() {
return next;
}
public void setNext(LinkedListNode next) {
this.next = next;
}
}
public class ListUtils {
public static LinkedListNode findTwoThirdsNode(LinkedListNode head){
int length=0;
LinkedListNode node=head.getNext();
LinkedListNode tmp=head;
double divresult=1;
while (node!=null){
length++;
divresult=(2*length)/3;
node=node.getNext();
if (divresult%1==0){
tmp=tmp.getNext();
}
}
if (length==1 || length==2){
return head;
}
else
return tmp;
}
}
You can do this by running over the linked list twice, but interleaved (in other words without a reset). You simply use a rabbit-and-tortoise-approach: you have the rabbit that hops three times per iteration, and the tortoise which hops twice each time:
LinkedListNode rabbit = head;
LinkedListNode tortoise = head;
while(rabbit != null) { //repeat until the rabit reaches the end of the list
for(int i = 0; rabbit != null && i < 2; i++) {
rabbit=rabbit.getNext(); //let the rabbit hop the first and second time
if(rabbit != null) {
tortoise=tortoise.getNext(); //let the tortoise hop the first and second time
}
}
if(rabbit != null) {
rabbit=rabbit.getNext(); //let the rabbit hop a third time
}
}
return tortoise; //if reached the end, we return where the tortoise ended
If you want the result to be as close as possible to 2/3rd (so not with much rounding errors), you better interleave the rabbit and tortoise hops as is done in the for loop. Furthermore you must do null checkings each time since it is possible that the length is not modulo three.
Keep 2 pointers, when you go thru the loop progress the left of them only 2/3 of the time.
when you reach the end of the loop return the pointer to the other node.
int i = 0;
node temp = head;
node progress = head;
while(progress != null) {
i++;
progress = progress.next;
if(i == 2 && progress != null) temp = temp.next;
else if ( i == 3 && progress != null) {
temp=temp.next;
i=0;
}
}
return temp;
}
this is the general idea
What about a simple for loop?
int n = // ...
int index = 2 * n / 3;
LinkedListNode current = head;
for(int i = 0 ; i < index ; ++i) {
current = current.next();
}
return current;
I want to maintain order of the elements being added in a list. So, I used a LinkedList in Java.
Now I want to be able to swap two elements in the linked list. First of all, I cannot find an elementAt() for LinkedList. Also, there is no way to add element at a specified position.
There is a Collections.swap(List<?> list, int i, int j) that you can use to swap two elements of a List<?>. There's also LinkedList.get(int index) and LinkedList.add(int index, E element) (both are methods specified by interface List). All of these operations will be O(N) since a LinkedList does not implements RandomAccess.
Check out the Javadocs for LinkedList
To find an element at an index use get(int index)
To place an element at a certain index use set(int index, Object element)
If you are writing your own LinkedList class for exercise (i.e. for a project or school), try making two temporary Object variables and two ints to hold their position in the List. Then, use add(int, Object) to add the first in the 2nd position, second in the 1st position.
public class SwapNode {
public static Node head;
public static void main(String[] args) {
SwapNode obj = new SwapNode();
obj.insertAtEnd(5);
obj.insertAtEnd(6);
obj.insertAtEnd(4);
obj.insertAtEnd(7);
obj.insertAtEnd(3);
obj.insertAtEnd(8);
obj.insertAtEnd(2);
obj.insertAtEnd(9);
obj.insertAtEnd(1);
obj.print(head);
System.out.println("*** Swapped ***");
obj.swapElementValue(4, 2);
}
public void swapElementValue(int value1, int value2) {
if (value1 == value2) {
System.out.println("Values same, so no need to swap");
return;
}
boolean found1 = false, found2 = false;
Node node = head;
while (node != null && !(found1 && found2)) {
if (node.data == value1) {
node.data = value2;
found1 = true;
node = node.next;
continue;
}
if (node.data == value2) {
node.data = value1;
found2 = true;
node = node.next;
continue;
}
node = node.next;
}
if (found1 && found2) {
print(head);
} else {
System.out.println("Values not found");
}
}
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
public void print(Node head) {
Node temp = head;
while(temp != null) {
System.out.print(temp.data);
temp = temp.next;
}
System.out.println();
}
static class Node {
private int data;
public Node next;
public Node(int data) {
this.data = data;
}
}
}
add
Does this what you want?
If you want to keep the list in a sorted state, why not just insert the element with addfirst
and then sort the list using Collections.sort
Take a look at ArrayList , this class will both maintain the insertion order and provide O(1) random access.
// I tried to reduce time complexity here, in 3 while loops (get() and set() use 4 while loop)
void swapAt(int index1, int index2){ // swapping at index
Node tmp = head;
int count=0;
int min, max; // for future reference to reduce time complexity
if(index1<index2){
min = index1;
max = index2;
}
else{
min = index2;
max = index1;
}
int diff = max - min;
while(min!=count){
tmp= tmp.next;
count++;
}
int minValue = tmp.data;
while(max!=count){
tmp= tmp.next;
count++;
}
int maxValue = tmp.data;
tmp.data = minValue;
tmp = head;
count =0;
while(min!=count){
tmp= tmp.next;
count++;
}
tmp.data = maxValue;
}