I've been stuck on this problem for quite a while. When I run it against my test for relocating index 1, I get from [A][B][C][D][E] to [B][B][C][D][E]. Any help would be much appreciated.
public void moveToTop(int index) throws IllegalArgumentException {
if (index > size) {
throw new IllegalArgumentException();
}
if (index == 0) {
return;
} else {
Node ref = first;
for (int i = 1; i < index; i++) {
ref = ref.next;
}
Node temp = null;
temp = ref.next;
ref = temp.next;
temp = first;
first = temp;
}
}
void moveToTop(int index) {
// index should go until size - 1, not size
if (index >= size) throw new IllegalArgumentException();
// index == 0 should return the list unmodified
if (index == 0) return;
// We start in the head
// first = A -> B -> C -> D -> E
// ref = A -> B -> C -> D -> E
Node ref = first;
for (int i = 0; i < index - 1; i++) {
// And loop until we find the node before the one we want to move
// For index = 1, we won't loop, so ref is still equal to first
ref = ref.next;
}
// temp = A.next => temp = B
Node temp = ref.next;
// ref (A) is the node before the one we wish to move
// A.next = B.next => A.next = C => ref = A -> C -> D -> E
ref.next = temp.next;
// B.next = A => temp = B -> A -> C -> D -> E
temp.next = first;
// first = B -> A -> C -> D -> E
first = temp;
}
Firstly, set the index in the loop to 0.
With what you have there, its content won't be executed.
Secondly, look very closely at the assignment logic that follows. You need to assign the ref node to the temp variable, the ref to the first node, and then the temp to the ref.
Try to use this for loop instead:
for (int i = 0; i <= index; i++) {
ref = ref.next;
}
Related
I want merging 2 list with these conditions
List<int> A = {1,1,1,null,null,null,null,null,null};
List<int> B = {null,null,null,2,2,2,null,null,null};
The result I want after merging
List<int> C = {1,1,1,2,2,2,null,null,null}
where the null value in list A will replace with a value in list B, Also in case there will have a case like 1 , null, 1, null I try to use it for loop but I cost a lot of performance I want a proper way to do it
for(int i = 0; i <A.size; i++)
{
for(int j=0 ;j <B.size; j++)
}
From my understanding of the question.
Case 1: If both Lists are of equal size then you can use Java stream API two write a consistent code without any loop.
List<Integer> C = IntStream.range(0, A.size())
.mapToObj(i -> {
Integer a = A.get(i);
Integer b = A.get(i);
if (a == null && b != null) {
return b;
} else if (a != null && b == null) {
return a;
} else {
// assuming when both the value are present
// you want to return from list A
return a;
}
})
.collect(Collectors.toList());
Case 2: If both lists can be of unequal size.
List<Integer> C = IntStream.range(0, Math.max(A.size(), B.size()))
.mapToObj(i -> {
Integer a = i < A.size() ? A.get(i) : null;
Integer b = i < B.size() ? B.get(i) : null;
if (a == null && b != null) {
return b;
} else if (a != null && b == null) {
return a;
} else {
// assuming when both the value are present
// you want to return from list A
return a;
}
})
.collect(Collectors.toList());
2 loops as you wrote it would mean your code runs the inner bit A * B times, which you don't want. You want to run it just 'A' times, assuming A and B are equal in size, or max(A.size(), B.size()) times if not.
var out = new ArrayList<Integer>();
for (int i = 0; i < a.size(); i++) {
Integer v = a.get(0);
if (v == null) v = b.get(0);
out.add(v);
}
I am trying to swap elements but the cycle is infinite.
The problem is in method change() or find().
I am just learning JAVA, so its hard to me to understand where is the mistake.
import java.util.*;
public class CustomLinkedList {
class Node{
int element;
Node next;
Node(int element){
this.element = element;
}
}
private Node first;
private Node last;
private int size;
private Node temp;
public void add(int element) {
Node newNode = new Node(element);
if(first == null) {
first = last = newNode;
} else {
last.next = newNode;
last = newNode;
}
size++;
}
public void output() {
Node current = first;
if(current == null) {
System.out.println("YOUR LIST IS EMPTY!!! ADD SOME ELEMENTS!!!");
}
else {
while(current != null) {
System.out.print("["+current.element+ "]" + " ");
current = current.next;
}
System.out.println();
}
}
public Node find(int index) {
Node current = first;
for(int i = 0; i < index; i++) {
current = current.next;
}
return current;
}
public void change(int index, int k) {
int count = 0;
while(count < k) {
Objects.checkIndex(index, size);
Node our = find(index);
temp = our.next;
our.next = our;
our = temp;
our = null;
count++;
index++;
}
}
}
Maybee, someone know how to do this.
When you swap two elements in a linked list, you actually need to modify up to three elements. For example, look at the following sub-list:
... -> a -> b -> c -> d -> ...
If you swap c and b, you get:
... -> a -> c -> b -> d -> ...
Now, the following has changed:
The next of a is now c (it was b).
The next of b is now d (it was c).
The next of c is now b (it was d).
Three nodes changed. Your code in the change() method only modifies two nodes, it forgets about node a.
Update
Possible implementation of a swap method:
/**
* Swaps the elements at the i-th and the (i-1)-th indices.
*/
public void swap(int index) {
Objects.checkIndex(index, size - 1);
if (index == 0) {
// Before swap: first -> x -> y
Node oldFirst = first;
Node x = first.next;
Node y = x.next;
// After swap: x -> first -> y
x.next = first;
first.next = y;
first = x;
// Update `last` if last two elements swapped
if (size == 2) {
last = oldFirst;
}
} else {
// Before swap: a -> b -> c -> d
Node a = find(index - 1);
Node b = a.next;
Node c = b.next;
Node d = c.next;
// After swap: a -> c -> b -> d
a.next = c;
b.next = d;
c.next = b;
// Update `last` if last two elements swapped
if (index == size - 2) {
last = b;
}
}
}
So, I'm trying to solve this question in my book, it asks for a Node swap in a given Linked List at given positions, well, I've tried implementing a method called "swap" and it gets stuck on an infinite loop, and I can't figure why
here's the method:
public void swap(LinkedList L1, int start, int end) {
Node ptr1, prev1, ptr2, prev2;
ptr1 = head;
prev1 = ptr1;
int count1 = 0;
int count2 = 0;
if ((start <= size()) && (start > 0) && (end <= size()) && (end > 0)) {
while (count1 != start && ptr1 != null) {
prev1 = ptr1;
ptr1 = ptr1.link;
count1++;
}
ptr2 = head;
prev2 = ptr2;
while (count2 != end && ptr2 != null) {
prev2 = ptr2;
ptr2 = ptr2.link;
count2++;
}
prev1.setLink(prev2.link);
ptr2.setLink(ptr1.link);
prev2.setLink(ptr1.link);
ptr1.setLink(ptr2.link);
}
}
and here's the main method, that I've trying to test the method in:
public static void main(String[] args) {
LinkedList L1 = new LinkedList();
L1.addToStart(5);
L1.addToStart(7);
L1.addToStart(23);
L1.addToStart(56);
L1.addToStart(52);
L1.addToStart(22);
L1.addToStart(57);
L1.addToStart(99);
L1.addToStart(34);
L1.addToStart(74);
L1.outputList();
L1.swap(L1, 2, 4);
L1.outputList();
You are not linking things correctly. You make both ptr2 and prev2 link to ptr1.link.
Assume this is the list
A -> B -> C -> D -> E -> F
and we want to switch B and E.
prev1 = A
ptr1 = B
prev2 = D
ptr1 = E
Relinked, it looks like
A -> B -> C -> D -> E -> F
|-------------------^
|-------------------^
^---------|
^--------|
A -> E -> C -> D -> B -> F
In code:
Node temp = ptr1.link;
prev1.setLink(ptr2);
ptr1.setLink(ptr2.link);
prev2.setLink(ptr1);
ptr2.setLink(temp);
I have been trying to come up with an algorithm to swap 2 nodes (not necesarily right next to each other) in a singly linked list for 2 days but for some reason I cannot do it.
Here is what I have, I am really new to coding and have been really stressed:
I have managed to place a temp node in but can't actually swap the nodes.
public void swap(int i, int j) {
current = head;
current2 = head;
sllNode temp = new sllNode(" ");
sllNode temp2 = new sllNode(" ");
for(int z = 0; i>z; z++)
current=current.next;
for(int q = 0; j>q; q++)
current2 = current2.next;
temp.next = current2.next.next;
current.next = temp;
current.next = current2.next.next;
current2.next = current;
Why exchange nodes, when you can exchange the data?
public void swap(int i, int j) {
sllNode ithNode = head;
for (int z = 0; z < i; z++) {
ithNode = ithNode.next;
}
sllNode jthNode = head;
for (int q = 0; q < j; q++) {
jthNode = jthNode.next;
}
// Swap the data
String data = ithNode.data;
ithNode.data = jthNode.data;
jthNode.data = data;
}
It would make sense to use a method:
public sllNode get(int i) {
sllNode current = head;
while (i > 0) {
current = current.next;
}
return current;
}
By the way:
The convention for class names is a beginning capital: SllNode.
Do not use fields for things like current and current2 where they can be local variables.
Exchanging nodes, the hard way
Here one has to think, so it is best to deal with special cases first, and then only treat i < j.
public void swap(int i, int j) {
if (i >= size() || j >= size()) {
throw new IndexOutOfBoundsException();
}
if (i == j) {
return;
}
if (j < i) {
swap(j, i);
return;
}
// i < j
sllNode ithPredecessor = null;
sllNode ithNode = head;
for (int z = 0; z < i; z++) {
ithPredecessor = ithNode;
ithNode = ithNode.next;
}
sllNode jthPredecessor = ithNode;
sllNode jthNode = ithNode.next;
for (int q = i + 1; q < j; q++) {
jthPredecessor = jthNode;
jthNode = jthNode.next;
}
// Relink both nodes in the list:
// - The jthNode:
if (ithPredecessor == null) {
head = jthNode;
} else {
ithPredecessor.next = jthNode;
}
sllNode jNext = jthNode.next;
//if (ithNode.next == jthNode) {
if (jthPredecessor == ithNode) {
jthNode.next = ithNode;
} else {
jthNode.next = ithNode.next;
}
// - The ithNode:
if (jthPredecessor == ithNode) {
} else {
jthPredecessor.next = ithNode;
}
ithNode.next = jNext;
}
No guarantee that the logic is okay. There are tricks:
//if (ithNode.next == jthNode) {
if (jthPredecessor == ithNode) {
Both conditions test whether i + 1 == j, but testing on a .next and then assigning makes the condition a momentary state. As you see it would have been easier to have one single if (i + 1 == j) { ... } else { ... } and handle both the ithNode and jthNode.
To do this, you need to swap 2 things: the node as next from the previous node, and the next node.
Once you found current and current2 which are the previous nodes of the nodes you want to swap, do this:
Swap the nodes:
sllNode tmp = current.next;
current.next = current2.next;
current2.next = tmp;
Then swap the next:
tmp = current.next.next;
current.next.next = current2.next.next;
current2.next.next = tmp;
// Swapping two elements in a Linked List using Java
import java.util.*;
class SwappingTwoElements {
public static void main(String[] args)
{
LinkedList<Integer> ll = new LinkedList<>();
// Adding elements to Linked List
ll.add(10);
ll.add(11);
ll.add(12);
ll.add(13);
ll.add(14);
ll.add(15);
// Elements to swap
int element1 = 11;
int element2 = 14;
System.out.println("Linked List Before Swapping :-");
for (int i : ll) {
System.out.print(i + " ");
}
// Swapping the elements
swap(ll, element1, element2);
System.out.println();
System.out.println();
System.out.println("Linked List After Swapping :-");
for (int i : ll) {
System.out.print(i + " ");
}
}
// Swap Function
public static void swap(LinkedList<Integer> list,
int ele1, int ele2)
{
// Getting the positions of the elements
int index1 = list.indexOf(ele1);
int index2 = list.indexOf(ele2);
// Returning if the element is not present in the
// LinkedList
if (index1 == -1 || index2 == -1) {
return;
}
// Swapping the elements
list.set(index1, ele2);
list.set(index2, ele1);
}
}
Output
Before Swapping Linked List :-
10 11 12 13 14 15
After Swapping Linked List :-
10 14 12 13 11 15
Time Complexity: O(N), where N is the Linked List length
I am working on an assignment where I have to sort an array and store the indices in a doubly linked list ADT that I have built.
Example:
{"A","B","C","A"} -> {0,3,1,2}
My current approach is to bring the indices into my ADT and then sort the ADT as I sort the array. As far as I can tell, I am doing the exact same operation on both the array and the doubly linked list every time either loop executes, but my output does not match up.
public static void main(String[] args ) {
List A = new List();
String[] inputArray = {"A","C","B","A"};
int i,j;
String key;
//load indices into doubly-linked list
for (int x = 0; x < inputArray.length; x++ ) {
A.append(x);
}
//begin insertion sort
for (j = 1; j < inputArray.length; j++) {
System.out.println(A);
System.out.println(Arrays.toString(inputArray));
key = inputArray[j];
i = j - 1;
while (i >= 0) {
if (key.compareTo(inputArray[i]) > 0) {
break;
}
inputArray[i+1] = inputArray[i];
//moveTo moves the cursor to <int>
A.moveTo(i);
//make sure we aren't trying to insert before first node
if (i > 0) { A.insertBefore(i+1); }
else { A.prepend(i+1); }
//remove node at cursor
A.delete();
i--;
}
inputArray[i+1] = key;
A.moveTo(i+1);
if (i > 0) { A.insertBefore(i+1); }
else { A.prepend(i+1); }
A.delete();
}
System.out.println(A);
System.out.println(Arrays.toString(inputArray));
}
The above code gives the following output:
run:
0 1 2 3
[A, C, B, A]
1 0 2 3
[A, C, B, A]
1 1 2 3
[A, B, C, A]
0 2 3 3
[A, A, B, C]
BUILD SUCCESSFUL (total time: 0 seconds)
EDIT: List.java
public class List {
private class Node{
//Fields
int data;
Node next, previous;
//Constructor
Node(int data) {
this.data = data;
next = null;
previous = null;
}
public String toString() { return String.valueOf(data); }
}
//Fields
private Node frontNode, backNode, cursorNode;
private int totalSize, cursorPosition;
//Constructor
List() {
frontNode = backNode = cursorNode = null;
totalSize = 0;
cursorPosition = -1;
}
//moveTo(int i): If 0<=i<=length()-1, moves the cursor to the element
// at index i, otherwise the cursor becomes undefined.
void moveTo(int i) {
if (i == 0) {
cursorPosition = i;
cursorNode = frontNode;
}
else if (i == length() - 1) {
cursorPosition = i;
cursorNode = backNode;
}
else if (i > 0 && i < length() - 1 ) {
cursorNode = frontNode;
cursorPosition = i;
for (int x=0; x < i; x++) {
cursorNode = cursorNode.next;
}
}
else {
cursorPosition = -1;
}
}
//prepend(int data): Inserts new element before front element in this List.
void prepend(int data) {
Node node = new Node(data);
if ( this.length() == 0 ) {
frontNode = backNode = node;
}
else {
frontNode.previous = node;
node.next = frontNode;
frontNode = node;
}
totalSize++;
//cursorPosition might change?
}
//insertBefore(int data): Inserts new element before cursor element in this
// List. Pre: length()>0, getIndex()>=0
void insertBefore(int data) {
Node node = new Node(data);
if ( this.length() > 0 && this.getIndex() >= 0 ) {
node.previous = cursorNode.previous;
node.next = cursorNode;
cursorNode.previous.next = node;
cursorNode.previous = node;
totalSize++;
}
else if ( this.length() <= 0 )
{
throw new RuntimeException
("Error: insertBefore called on empty list");
}
else {
throw new RuntimeException
("Error: insertBefore called without cursor set");
}
}
OK, thanks. I didn't know exactly what insertBefore() and prepend() were intended to do (I could have guessed, but programming should not be about guessing what methods are supposed to do; seeing the documentation is much better).
Since this is an assignment, I'm not going to give you the answer. But the clue is this: After the first pass through the loop, the dump of A gives you the same indices you started with, but rearranged. I think that's the way it's supposed to be after every loop iteration. But that's not true after the second pass through the loop (1 shows up twice, and 0 is gone). Think about it. When you called A.insertBefore() to rearrange the elements of A, what data should you have told insertBefore() to insert, and what did you actually insert?