I have written a code to swap elements of linkedList in Java.
Currently, my code fails, i.e., it is not swapping elements. I am having difficulty
on how to approach to this problem. Any tips?
public void switchPairs(){
if (front==null || front.next==null)
return ;
ListNode temp=front;
front=front.next;
ListNode curr=front;
while(curr.next!=null){
ListNode dummy = curr.next;
curr.next=temp;
temp.next=dummy;
temp=temp.next;
curr=dummy;
}
}
Input : front -> [3] -> [7] -> [4] -> [9] -> [8] -> [12] /
Expected output: front -> [7] -> [3] -> [9] -> [4] -> [12] -> [8] /
my output: front -> [7] -> [3] -> [4] -> [9] -> [8] -> [12] /
The way I approach this problem is
Draw the linkedList for the input and desired output in the right format for the simplest case. Here I would start with 4 nodes;
Then tackle the easy cases such as if the ListNode or the next is null
On the paper, mark the links that are broken and that are formed. Note you have to do the breaking and linking in right order; Make sure you have reference to the nodes whose link you are breaking. otherwise you might end up losing some nodes. That is the whole crux here. Draw after each step when a node is broken or a link is formed. In this way, you can keep track of what is going;
Translate what you have drawn on paper to code. That must be fairly straightforward!
Often you would need to have temporary pointers to traverse the list;
In this example, the front or head pointer needs to be changed. so I would do the first swap outside an iteration. The remaining changes I would inside a while loop.
write a convienient toString method that can help you track the variables at each stage. I found it harder to use debuggers forrecusions and linkedLists. but that is just me.
Regarding the solution for this problem: This is not as easy problem in my opinion. but a good one to get a good grasp of linkedLists andPointers`
here is my solution:
public void switchPairs(){
if (front==null || front.next==null)
return ;
//keep a pointer to next element of front
ListNode current=front.next;
//make front point to next element
front.next=current.next;
current.next=front;
front=current;
//current has moved one step back it points to first.
//so get it to the finished swap position
current=current.next;
while(current.next!=null && current.next.next!=null){
ListNode temp = current.next.next;
current.next.next=temp.next;
temp.next=current.next;
current.next=temp;
current=temp.next;
}
}
The best way to answer a question like this to to visualize the state of your list as it progresses thru the iteration. I have implemented the code with a println to help with that. The other choice is to include variable names that are easier to keep track of, while temp and dummy will not prevent you from achieving correctness they are more difficult to follow.
This is the function
public ListNode switchPairs(){
if (this==null || this.next==null)
return this;
ListNode top = this.next;
ListNode first = this;
ListNode second = first.next;
do {
ListNode third = second.next;
second.next = first;
first.next = third;
first = third;
System.out.println("### " + top.toString());
if (first != null) {
// remember second now is really the first element on the list
// at this point.
second.next.next = first.next;
second = first.next;
}
} while(first != null && second != null);
return top;
}
And this is the entire code
public class ListNode {
private ListNode next = null;
private final int i;
ListNode(int i) {
this.i = i;
}
ListNode(int i, ListNode parent) {
this(i);
parent.next = this;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("[" + this.i + "]");
if (this.next != null) {
sb.append("->");
sb.append(this.next.toString());
}
return sb.toString();
}
public static void main(String[] args) {
ListNode top = null;
ListNode curr = null;
for(String arg : args) {
int i = Integer.parseInt(arg);
if(curr == null)
curr = new ListNode(i);
else
curr = new ListNode(i, curr);
if( top == null)
top = curr;
}
System.out.println(top.toString());
top = top.switchPairs();
System.out.println(top.toString());
}
public ListNode switchPairs(){
if (this==null || this.next==null)
return this;
ListNode top = this.next;
ListNode first = this;
ListNode second = first.next;
do {
ListNode third = second.next;
second.next = first;
first.next = third;
first = third;
System.out.println("### " + this.toString());
if (first != null) {
second.next.next = first.next;
second = first.next;
}
} while(first != null && second != null);
return top;
}
}
Last but not least a sample output
java ListNode 1 2 3 4 5 6 7 8
[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]
### [2]->[1]->[3]->[4]->[5]->[6]->[7]->[8]
### [2]->[1]->[4]->[3]->[5]->[6]->[7]->[8]
### [2]->[1]->[4]->[3]->[6]->[5]->[7]->[8]
### [2]->[1]->[4]->[3]->[6]->[5]->[8]->[7]
[2]->[1]->[4]->[3]->[6]->[5]->[8]->[7]
public void switchPairs() {
ListNode prev = front;
if(front!=null && front.next != null) {
ListNode temp = front;
front = front.next;
temp.next = front.next;
front.next = temp;
prev = temp;
}
while(prev !=null && prev.next != null && prev.next.next != null) {
ListNode first_node =prev.next;
ListNode second_node = first_node.next;
first_node.next = second_node.next;
second_node.next = first_node;
prev.next = second_node;
prev = first_node;
}
}
// Recursive solution
public void switchPairs(SingleLinkListNode prev, SingleLinkListNode node) {
if (node == null || node.next == null) {
return;
}
SingleLinkListNode nextNode = node.next;
SingleLinkListNode temp = nextNode.next;
nextNode.next = node;
node.next = temp;
if (prev != null) {
prev.next = nextNode;
} else {
head = nextNode;
}
switchPairs(node, node.next);
}
I have this recursive function, which works:
public void swap2List(){
root = swap2List(root); //pass the root node
}
private Node swap2List(Node current){
if(current == null || current.next == null){
return current;
}
else{
Node temp = current;
Node temp2 = current.next.next;
current = current.next;
current.next = temp;
temp.next = swap2List(temp2);
}
return current;
}
public static LinkedList<Integer> switchPairs(LinkedList list) {
ListIterator<Integer> iterator = list.listIterator();
LinkedList<Integer> out = null;
while (iterator != null && iterator.hasNext()) {
if (out == null) {
out = new LinkedList<Integer>();
}
int temp = iterator.next();
if (iterator.hasNext()) {
out.add(iterator.next());
out.add(temp);
}else{
out.add(temp);
}
}
return out;
}
Related
I am trying to reverse a subpart of a singly-linked list where the subpart is a contiguous set of even elements, bordered by either the end of the list or an odd element.
So far, I know how to reverse a linked list but I'm unable to figure out how to check if the element is odd or if it's at the end.
Node reverse(Node head) {
// Write your code here
if(head == null) return null;
Node prev = null;
Node curr = head;
Node next = null;
while(curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
Example
Input:
list = [1, 2, 8, 9, 12, 16]
Output:
[1, 8, 2, 9, 16, 12]
The subparts in this example are 2,8 and 12,16
Node reverse(Node head) {
if(head == null) return null;
Node curr = head;
Node next = null;
Node prev = null;
while(curr!=null && curr.data%2==0) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
if(curr!=head) {
head.next = curr;
curr = reverse(curr);
return prev;
} else {
head.next = reverse(head.next);
return head;
}
}
Q. Given a singly linked list of integers, reverse every contiguous set of nodes that have only even values.
I/P = 1 2 3 3 4 6 8 5, O/P = 1 2 3 3 8 6 4 5, explanation -
There are two sub lists of even elements, which [2] and [4->6->8]. The sub list [4->6->8] has been reversed and the single sub list [2] need not be reversed.
Test Cases passed
1 3 8 3 4 2 6 5 single/multi even element in list,
2 4 6 1 3 even occurs at head,
1 4 4 6 8 even occurs till tail,
2 4 6 8 2 all even in the list
import java.util.*;
//import ds.List.ListNode; import your ListNode class
/*
public class ListNode {
public int val;
public ListNode next;
public ListNode(int x) { val = x; next = null; }
}
*/
class Solution{
public ListNode reverseEvenElements(ListNode head)
{
ListNode p = null;//prev
ListNode c = head;//curr
while(c != null){
if(c.val % 2 == 0){
ListNode start = p;
while(c != null && c.val % 2 == 0){
p = c;
c = c.next;
}
//end of even elements = p
//making end of even node to null so that reverse should stop
//otherwise it will reverse whole list
p.next = null;
ListNode[] node;// [head,tail]
// if start is null i.e. even element found at head itself
if(start == null){
node = reverseList(head);
head = node[0];//node[0] = head of reversed list
}else{// start != null
node = reverseList(start.next);
start.next = node[0];
}
node[1].next = c;//node[1] = tail of reversed list
}
if(c != null){
p = c;
c = c.next;
}
}
return head;
}
// this method will be called when even elements occurs till last even element we get
//in the original list returns head & tail of reversed list
public static ListNode[] reverseList(ListNode head){
ListNode p = null;
ListNode c = head;
ListNode n = head.next;
while(true){
c.next = p;
p = c;
c = n;
if(n == null)
break;
else
n = n.next;
}
return new ListNode[] {p, head};// [head,tail]
}
}
from what you given me i understood like :
input : [1,2,4,8,5,7,7,6,6,2,8,1,1,1,2,4]
output: [1,8,4,2,5,7,7,8,2,6,6,1,1,1,4,2]
i have edited your code for reverse to reverse till which will reverse intervals & created reverse_whole which will find those intervals
public ListNode reverse_whole(ListNode head) {
ListNode temp=head;
ListNode pre_temp=new ListNode(0,temp);
ListNode ans_pre = pre_temp;
while(temp!=null){
if(temp.val%2==0){
ListNode temp_till=temp;
while(temp_till!=null&& temp_till.val%2==0){
temp_till=temp_till.next;
}
// temp_till will iterate over even number interval after one
//so: 1,2,4,6,7 : 7 is temp_till
// reverse 2,4,6 so it become : 1,6,4,2,7
pre_temp.next=reverse_subpart(temp,temp_till);
temp=temp_till;
}
pre_temp=temp;
if(temp!=null)temp=temp.next;
}
return ans_pre.next;
}
public ListNode reverse_subpart(ListNode head,ListNode end) {
// Write your code here
if(head == null) return null;
ListNode prev = null;
ListNode curr = head;
ListNode next = null;
while(curr != end) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head.next=end;
return prev;
}
run reverse_whole
if you have any doubt can write me
class LinkedList {
Node head;
Node curr = head;
Node next = null;
Node prev = null;
class Node {
int data;
Node next;
Node(int d)
{
data = d;
next = null;
}
}
void pairWiseSwap()
{
Node temp = head;
while (temp != null && temp.next!=null) {
int k = temp.data;
int j = temp.next.data;
if(k%2==0 && j%2==0) {
temp.data=j;
temp.next.data=k;
temp=temp.next.next;
continue;
}
temp = temp.next;
}
}
public void push(int new_data)
{
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
void printList()
{
Node temp = head;
while (temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
}
System.out.println();
}
public static void main(String args[])
{
LinkedList llist = new LinkedList();
llist.push(16);
llist.push(12);
llist.push(9);
llist.push(8);
llist.push(2);
llist.push(1);
System.out.println("Linked List before calling pairWiseSwap() ");
llist.printList();
llist.pairWiseSwap();
System.out.println("Linked List after calling pairWiseSwap() ");
llist.printList();
}
}
// Complete the sortedInsert function below.
/*
* For your reference:
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode next;
* DoublyLinkedListNode prev;
* }
*
*/
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode Leader=head;
DoublyLinkedListNode newNode = new DoublyLinkedListNode(data);
while(Leader.next!=null){
if(data>Leader.data){
Leader = Leader.next;
}
else {
if(Leader.prev == null) {
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
if(Leader.next == null) {
if(data<Leader.data) {
newNode.prev = Leader.prev;
newNode.next = Leader;
Leader.prev.next = newNode;
return head;
} else {
newNode.prev = Leader;
Leader.next = newNode;
return head;
}
}
return head;
}
in the above-sorted insert method how to decrease this doubly linked list complexity, this is a hackerrank question I'm getting timed outs for the test cases I need help in decreasing the time complexity for this code.
You code will never come out of while loop.
Lets take the example. List = [(1), (4), (4)](only 1 element). New node is (4). Your result should be [(1), (4), (4), (4)]. But lets walk your code and check what will happen. Initially Leader = (1)
while(Leader.next!=null){ // 1
if(data>Leader.data){ // 3
Leader = Leader.next;
}
else { // 6
if(Leader.prev == null) { // 7
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
At line 1 check will pass (as (1).next is not null; in fact it is (4)).
At line 3 ((4) > (1)). Check pass. Leader = (1).next = (4). Jump to line 1
At line 1 check will pass (as (4).next is not null; in fact it is (4)).
At line 3 ((4) > (4)). Check Fail. Enter line 7
At line 7 check will fail ((4).prev is not null; in fact it is (4) - 1st 4). No update in Leader will take place. Leader will remain same & you will enter infinte loop from here.
You will have to take care of this. Maybe the Problem's discussion page will help. But do give it a through try.
My own try is included below:
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode n = new DoublyLinkedListNode();
n.data = data;
DoublyLinkedListNode curr = head;
if (head == null) {
return n;
}
// if given node is smaller than 1st node
if (data < curr.data) {
n.next = curr;
return n;
}
// find first node greater than given node
while (curr.next != null && curr.data < data) {
curr = curr.next;
}
// reached to the end.
if (curr.next == null && data >= curr.data) {
curr.next = n;
} else { // found the 1st node which is greater than given node
curr.prev.next = n;
n.next = curr;
}
return head;
}
I'm trying a standard interview question, which is to add two digits in the form of linkedlists and return the added answer. Here is the question:
You are given two linked lists representing two non-negative numbers.
The digits are stored in reverse order and each of their nodes contain
a single digit. Add the two numbers and return it as a linked list.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8
342 + 465 = 807 Make sure there are no trailing zeros in the output list So, 7 -> 0 -> 8 -> 0 is not a valid response even though
the value is still 807.
Now, the code I am writing takes in two arguments in the form of ListNode datatypes which is the starting node of the LinkedLists. What I am not understanding is
How do I maintain the head node of the list to reference later?
How does call by value and call by reference work in Java? I've dealt with pointers and call by reference in C++ but I've been trying stuff in Java now and it's pretty different.
class ListNode {
public int val;
public ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
public ListNode reverse(ListNode head) {
ListNode curr = head;
ListNode next = null;
ListNode prev = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
public ListNode addTwoNumbers(ListNode a, ListNode b) {
ListNode node = null;
ListNode head = null;
boolean carry = false;
while (a != null || b != null) {
int f = 0, s = 0;
if (carry) {
f++;
}
carry = false;
if (a != null) {
f += a.val;
a = a.next;
}
if (b != null) {
s = b.val;
b = b.next;
}
if (f + s > 9) {
carry = true;
}
int curr = (f + s) % 10;
node = new ListNode(curr);
if (head == null) {
head = node;
}
node = node.next; //warning that 'value of node assigned is never used'
}
if (carry) {
node = new ListNode(1);
}
printList(head);
return node;
}
}
node plays an ambiguous role.
node = new ListNode(curr);
node = node.next; // assigns null
Rename node into previous and do:
int curr = (f + s) % 10;
ListNode newNode = new ListNode(curr);
if (head == null) { // Or `previous == null`
head = newNode;
} else {
previous.next = newNode;
}
previous = newNode;
...
return head;
The technique to handle head is to make it a private field of a container class LinkedList.
As in java the parameter passing is call-by-value: f(a) never changes the variable a: the slot where the object pointer / value is stored. Instead to object pointer / value is pushed on the stack. (The object value may have its fields changed.)
So a recursive insert might look like head = insert(head, ...).
In C on can use aliasing, not only for parameter passing:
ListNode* head = NULL;
ListNode** node = &head;
shile (...) {
...
*node = newNode;
node = &(newNode->next);
}
Why so complicated?
public class Solution {
public ListNode addTwoNumbers(ListNode a, ListNode b) {
int firstNumber = nodeToNumber(a);
int secondNumber = nodeToNumber(b);
return numberToNode(firstNumber + secondNumber);
}
public int nodeToNumber(ListNode node) {
if (node.next != null) return node.value + 10 * nodeToNumber(node.next);
return node.value;
}
public ListNode numberToNode(int number) {
ListNode result = new ListNode(number % 10);
if (number > 10) result.next = numberToNode(number / 10);
return result;
}
}
I'm trying to learn about linked list and it has been little challenging for me. I'm trying to reverse the link list with recursive method. Here is my code:
public class ListNode {
Node head = null;
int nodeCount= 0;
int counter = 0;
ListNode(){
head = null;
}
public void insertNode( String name ) {
if (head == null) {
head = new Node(name, null);
nodeCount++;
} else {
Node temp = new Node(name, null);
temp.next = head;
head = temp;
nodeCount++;
}
}
public Node reverseTest(Node L){
// Node current = new Node(null,null);
if(L == null || L.next ==null){
return L;
}
Node remainingNode = reverseTest(L.next);
Node cur = remainingNode;
while(cur.next !=null){
cur=cur.next;
}
L.next = null;
cur.next = L;
return remainingNode;
}
public static void main(String[] args){
ListNode newList = new ListNode();
newList.insertNode("First");
newList.insertNode("Second");
newList.insertNode("Third");
newList.insertNode("Fourth");
newList.reverseTest(newList.head);
}
}
The problem I'm having with is the reverse method. When the method is over it only returns the last node with the value "First".Through the entire recursion remainingNode only holds and returs value from the base case which is confusing me. I was excepting it to move further through the nodes. After the method is executed newList holds only one node with next node as null and that node is the head now. I was assuming it will reverse the linkedlist with the sequence First --> Second--> Third --> Fourth. What am I doing wrong?
Actually, everything works here. Your only problem is in your main method: you don't get the result of your method.
newList.reverseTest(newList.head);
You need to actually set the new head with the result:
newList.head = newList.reverseTest(newList.head);
This would have been easier to see if you had declared your method static:
newList.head = ListNode.reverseTest(newList.head);
As a bonus, here is a fully recursive equivalent:
public static Node reverse(Node head) {
if (head == null || head.next == null) {
return head;
}
Node newHead = reverse(head.next);
// head.next points to the new tail, we push the former head at the end
head.next.next = head;
// now head has become the new tail, we cut the end of the list
head.next = null;
return newHead;
}
I want to remove duplicates from sorted linked list {0 1 2 2 3 3 4 5}.
`
public Node removeDuplicates(Node header)
{
Node tempHeader = null;
if(header != null)
tempHeader = header.next;
else return header;
Node prev = header;
if((tempHeader == null)) return header ;
while(tempHeader != null)
{
if(tempHeader.data != prev.data)
{
prev.setNext(tempHeader);
}
tempHeader = tempHeader.next;
}
prev = header;
printList(prev);
return tempHeader;
}
`
prev.setNext(tempHeader) is not working correctly inside the while loop. Ideally when prev = 2 and tempHeader = 3, prev.next should be node with data = 3.
Printlist function just takes header pointer and prints the list.
Node definition is given below.
public class Node
{
int data;
Node next;
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
The loop is sorted, so you know that duplicates are going to sit next to each other. If you want to edit the list in place then, you've got to have two list pointers (which you do). The one you call tempHeader and prev, and you've got to advance them both in the the list as you go (which I don't see in the code). Otherwise, if you don't advance the prev pointer as you go, then you're always comparing the element under tempHeader to the first item in the list, which is not correct.
An easier way to do this, however, is to build a new list as you go. Simply remember the value of the last item that you appended to the list. Then if the one that you're about to insert is the same then simply don't insert it, and when you're done, just return your new list.
I can give you 2 suggestions for the above suggestion
1) Convert the linked List to Set, that will eliminate the duplicates and
Back from Set to the Linked list
Code to get this done would be
linkedList = new LinkedList<anything>(new HashSet<anything>(origList));
2) You can use LinkedHashSet, if you dont want any duplicates
In this case no return value is needed.
public void removeDuplicates(Node list) {
while (list != null) {
// Walk to next unequal node:
Node current = list.next;
while (current != null && current.data.equals(list.data)) {
current = current.next;
}
// Skip the equal nodes:
list.next = current;
// Take the next unequal node:
list = current;
}
}
public ListNode removeDuplicateElements(ListNode head) {
if (head == null || head.next == null) {
return null;
}
if (head.data.equals(head.next.data)) {
ListNode next_next = head.next.next;
head.next = null;
head.next = next_next;
removeDuplicateElements(head);
} else {
removeDuplicateElements(head.next);
}
return head;
}
By DoublyLinked List and using HashSet,
public static void deleteDups(Node n) {
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while (n != null) {
if (set.contains(n.data)) {
previous.next = n.next;
} else {
set.add(n.data);
previous = n;
}
n = n.next;
}
}
doublylinkedList
class Node{
public Node next;
public Node prev;
public Node last;
public int data;
public Node (int d, Node n, Node p) {
data = d;
setNext(n);
setPrevious(p);
}
public Node() { }
public void setNext(Node n) {
next = n;
if (this == last) {
last = n;
}
if (n != null && n.prev != this) {
n.setPrevious(this);
}
}
public void setPrevious(Node p) {
prev = p;
if (p != null && p.next != this) {
p.setNext(this);
}
}}