LinkedList function from InterviewBit - java

I'm struggling with my solution for a question on InterviewBit.
I linked to the full description, but in short:
1) You are given the head node of a linkedlist
2) take the first half of the list and change the values so that:
"1st node’s new value = the last node’s value - first node’s current value
2nd node’s new value = the second last node’s value - 2nd node’s current value"
Here is my approach (it compiles but does not mutate the list at all)
I see that my method does not actually modify the original list -- it seems like what I'm doing is making a new list with the correctly altered values, but not changing the original.
/**
* Definition for singly-linked list.
* class ListNode {
* public int val;
* public ListNode next;
* ListNode(int x) { val = x; next = null; }
* }
*/
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
while(current.next != null){
double half = Math.floor(length/2);
for(int i=0; i<half; i++ ){
//
// if(i == 0){
// int aval = (nthToLast(a, length)).val - a.val;
// a.val = ((nthToLast(a, length-i)).val - a.val);
// a.next = current;
// }
current.val = ((nthToLast(a, length-i)).val - current.val);
current = current.next;
}
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth to last ListNode in the LinkedList */
public ListNode nthToLast(ListNode head, int n){
ListNode nth = head;
ListNode ahead = head;
/* strategy: set nth to head, and 'ahead' to n places in front of 'nth'
increment at same speed and then when 'ahead' reaches the end, 'nth'
will be in the nth place from the end.
*/
while(ahead.next != null){
for(int i=0; i<n; i++){
ahead = ahead.next;
}
nth = nth.next;
ahead = ahead.next;
}
return nth;
}
}
Also -- I'm trying to get better at questions like these. Is this an ok approach for this question? I'd like to figure out how to make this work, but also if this is an all around bad approach please let me know.

break code into simple helper functions,
make a function to get value of nth element in the linked list(this function is very easy to write)
,and then traverse the list upto the half every time calling that function to get the value of listSize-i member of the list and edit the value of the the ith member of the list. and make changes to the 1st few elements manually to check weather your linkList implementation is working or not
/**
* Definition for singly-linked list.
**/
class ListNode {
public int val;
public ListNode next;
ListNode(int x) { val = x; next = null; }
}
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
int half = length/2;
//logic of this loop is
//go from 0 to half of the list
// j goes from the last element to half
//for example if size of list is 6 (indexing from 0)
//when i is 0 j is 5
//when i is 1 j is 4 and so on
//so you get what you wanted
for(int i=0,j=length-1; i<half; i++,j-- ){
current.val=nthElement(a,j).val-current.val;
current = current.next;
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth node of LinkedList */
public ListNode nthElement(ListNode head, int n){ //e.g-if n is 5 it will return the 5th node
ListNode nth = head;
for(int i=0; i<n; i++){
nth = nth.next;
}
return nth;
}
}

Related

LinkedList sum function deletes the entire list once finished?

This is for practice purposes not a real world problem.
I am summing all the nodes of int data type in a linked list this works fine.
I am also summing all the nodes with even numbers of int data type in a linked list this works fine.
But when I call one after the other in the test class the entire list is empty(Well set to null).
I think it is to do with this line head = head.next;
data() returns the data stored on that node
TEST Class
linkedList.addTail(4);
linkedList.addTail(7);
linkedList.addTail(2);
linkedList.addTail(7);
linkedList.sum();
//The list is empty here
linkedList.sumEven();
Linked List
public int sum(){
int sum = 0;
while (head != null) {
sum += head.data;
//Here
head = head.next;
}
System.out.println(sum);
return sum;
}
public int sumEven(){
//To keep track of the sum
int sum = 0;
while (head != null)
{
//If the data at head is even add
if (head.data() % 2 == 0)
sum += head.data;
//Or Here
head = head.next;
}
System.out.println(sum);
return sum;
}
You are overriding head every time you assign it. You can either make a copy of it before summing or sum using a for like similar to the following.
for(Integer i: head) sum += i;
I have assumed that the elements in your LinkedList are of type int.

Finding the 'maximum' character in a linked list Java recursively

I am trying to find the "maximum" value in a linked list recursively using a helper function. I am just starting to learn about these in my class and am pretty confused. We have a custom class that defines the type Node and another function to calculate the size of the Node or linkedlist. I solved this problem when I was comparing integers, but with characters I am lost. Here is my code:
'''
static class Node {
public Node (char item, Node next) { this.item = item; this.next = next; }
public char item;
public Node next;
}
Node first; // this is the only instance variable,
// the access point to the list
// size
//
// a function to compute the size of the list, using a loop
// an empty list has size 0
public int size () {
int count = 0;
for (Node tmp = first; tmp != null; tmp = tmp.next)
count++;
return count;
}
/*
* maxCharacter
*
* a function to compute the 'maximum' character in the list using recursion
* You will want to create a helper function to
* do the recursion
*
* precondition: list is not empty
*
* Examples:
* ["ababcdefb"].maxCharacter() == 'f'
* ["eezzg"].maxCharacter() == 'z'
* ["a"].maxCharacter() == 'a'
*/
public char maxCharacter () {
return maxCharacterHelper(first, first.size());
}
public char maxCharacterHelper(Node first, int index) {
char[] alpha = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int max = 0;
while(index > 0 )
max = alpha.indexOf(first.item) > max ? first.item : max;
maxCharacterHelper(first, index-1);
return max;
}
'''
If you could explain how I would loop through the list recursively while maintaining the greatest char I would greatly appreciate it.
The golden rule with recursion is "Think of the base case first, then write the recurrence".
In this case, the base is the empty list. In this case, the maximum is the last value you've seen.
The recurrence is just a call to the rest of the list with the highest value you've called.
public static MaxNode(Node n, char currentMax) {
if (n == null) // base case, we're at the end.
return currentMax;
// recurrence
return MaxNode(n.next, currentMax > n.item ? currentMax : n.item);
}
For simple ASCII values, you can treat the maximum using the > operator.
Your while loop is confusing because of indentation and because you never change index. However, I don't think you need it if your intent is to use recursion. Generally with recursion you need to establish a base case from which you cannot recurse. For a linked list the natural base case is where there is no next node, rather than index-based.
if (current.next == null)
return alpha.indexOf(current.item);
Otherwise combine the recursion return with the current value
int remainingMax = maxCharacterHelper(current);
int currentValue = alpha.indexOf(current.item);
return (remainingMax > currentValue) ? remainingMax : currentValue;
Here is how I would put it together
//I made it static because it is not a method of a specific Node
public static int maxCharacterHelper(Node currentNode){
// remaining list includes only current node, so this one has max value
if (current.next == null)
return alpha.indexOf(current.item);
//otherwise take the larger of remaining list and current node
int remainingMax = maxCharacterHelper(current.next);
int currentValue = alpha.indexOf(current.item);
return (remainingMax > currentValue) ? remainingMax : currentValue;
}

Searching from beginning of a list and end of a list (Java)

I am confused on how to search from the beginning of the list or from the end of the list.
EDIT: This is code have over 200 lines so if you need anything else please ask. I have added the Node class.
Return node number k.Precondition: 0 <= k < size of the list. If k is 0, return first node; if k = 1, return second node, ...
public Node getNode(int k) {
//TODO 4. This method should take time proportional to min(k, size-k).
// For example, if k <= size/2, search from the beginning of the
// list, otherwise search from the end of the list.
if (k <= size/2) {
}else {
}
return null;
}
public class Node {
private Node prev; // Previous node on list (null if this is first node)
private E val; // The value of this element
private Node next; // Next node on list. (null if this is last node)
/** Constructor: an instance with previous node p (can be null),
* value v, and next node n (can be null). */
Node(Node p, E v, Node n) {
prev= p;
val= v;
next= n;
}
/** Return the node previous to this one (null if this is the
* first node of the list). */
public Node prev() {
return prev;
}
/** Return the value of this node. */
public E value() {
return val;
}
/** Return the next node in this list (null if this is the
* last node of this list). */
public Node next() {
return next;
}
}
}
Assuming you actually need to search through a list rather than just returning myNodeList.get(k)then see below:
Take a look at a normal loop:
for (int index=0; index < size; index++) {
//do something
}
That loop starts at index 0 (index=0), it finishes once index is greater than size (index < size), and increases each loop (index++), but we could easily modify it to start at the maximum size/end index=size-1, to finish at 0 (index >= 0), and decrease each loop (index--).
So from beginning:
for (int index=0; index < myNodeList.size(); index++) {
//do something
}
From end:
for (int index=size-1; index >= 0; index--) {
//do something
}

Measure size/length of singly linked list in Java?

I need help making the int size(); method for a singly linked list in Java.
This is what I have so far, but it does not return the correct size of the list.
public int size()
{
int size = 0;
Node CurrNode = head;
while(CurrNode.next != null)
{
CurrNode = CurrNode.next;
size++;
}
return size;
}
Can someone help me implement this method in Java?
The biggest improvement you can make is to use Java Coding Convension and use camelCase local variables.
You can write it like this.
public int size() {
int size = 0;
for(Node n = head; n.next != null; n = n.next)
size++;
return size;
}
as you are re-writing a commonly used class in Java, I suggest you have a look at how it is done there if you want a better way of doing things.
From LinkedList
/**
* Returns the number of elements in this list.
*
* #return the number of elements in this list
*/
public int size() {
return size;
}
As you can see, when an element is added size is incremented and when an element is removed it id decremented saving you having to traverse the list to get the size.
The easiest way would be to have variable that tracks the size initialised at 0. Then each time you add a node it's just size++, or size-- when you remove a node. You size() method then just has to return this variable without traversing the list.
You need to pass the list to your method and check currNode!= null :
public static int size(Node currNode){
int count = 0;
while (currNode!= null){
count++;
currNode=currNode.getNext();
}
return count;
}
Well, the easiest way to calculate the length is by checking whether the currentNode!=null and keep the currentNode incrementing .
We can use while or a for loop to implement this.
Below is an example where for loop is used.
public int getLength(){
ListNode temp = head;
for(temp = head; temp!=null; temp=temp.getNextNode()){
length++;
}
return length;
}

How can I reverse a linked list?

Consider:
Node reverse(Node head) {
Node previous = null;
Node current = head;
Node forward;
while (current != null) {
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
How exactly is it reversing the list?
I get that it first sets the second node to forward. Then it says current.next is equal to a null node previous. Then it says previous is now current. Lastly current becomes forward?
I can't seem to grasp this and how it's reversing. Can someone please explain how this works?

			
				
You reverse the list iteratively and always have the list in the interval [head, previous] correctly reversed (so current is the first node that has its link not set correctly). On each step you do the following:
You remember the next node of current so that you can continue from it
You set the link of current to be pointing to previous, which is the correct direction if you think about it
You change previous to be current, because now current also has its link set correctly
You change the first node that does not have its link set correctly to be the one remembered in the first step
If you do that for all the nodes, you can prove (with induction for instance) that the list will be correctly reversed.
The code simply walks the list and inverts the links until it reaches the previous tail, which it returns as the new head.
Before:
Node 1 (Head) -> Node 2 -> Node 3 -> Node 4 (Tail) -> null
After:
null <- Node 1 (Tail) <- Node 2 <- Node 3 <- Node 4 (Head)
The easiest way to think about it is to think like this:
First add the head of the list to a new linked list.
Keep iterating through the original and keep adding the nodes before the head of the new linked list.
Diagram:
Initially:
Original List -> 1 2 3 4 5
New List -> null
1st Iteration
Original List -> 1 2 3 4 5
New List -> 1->null [head shifted to left, now newHead contains 1 and points to null]
2nd Iteration
Original List -> 1 2 3 4 5
New List -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
3rd Iteration
Original List -> 1 2 3 4 5
New List ->3 -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
Now it keeps looping through till the end. So finally the new list becomes:
New List-> 5 -> 4 -> 3 -> 2 -> 1 -> null
The code for the same should be like this (made it easy to understand):
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public ListNode reverseList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode current = head;
ListNode previous = new ListNode(head.val);
previous.next = null;
while(current.next != null) {
current = current.next;
previous = addBeforeHead(current, previous);
}
return previous;
}
private ListNode addBeforeHead(ListNode node, ListNode head) {
if (node == null) return null;
ListNode temp = new ListNode(node.val);
temp.next = head;
head = temp;
return head;
}
public Node getLastNode()
{
if(next != null)
return next.getLastNode();
else
return this;
}
public Node reverse(Node source)
{
Node reversed = source.getLastNode();
Node cursor = source;
while(cursor != reversed)
{
reversed.addNodeAfter(cursor.getInfo());
cursor = cursor.getNodeAfter();
}
source = reversed;
return source;
}
I call it "cherry picking". The idea is to minimize the number of swaps. Swapping happens between a near and far index. It's a twp-pass algorithm.
(Odd length) A -> B -> C -> D -> E
(Even length) A -> B -> C -> D
Pre-Condition: N >= 2
Pass 1: Count N, the number of elements
Pass 2:
for(j=0 -> j<= (N/2 -1))
{
swap(j, (N-1)-j)
}
Example 1:
For above Odd length list, N = 5 and there will be two swaps
when j=0, swap(0, 4) // Post swap state: E B C D A
when j=1, swap(1, 3) // Post swap state: E D C B A
The mid point for odd length lists remains intact.
Example 2:
For above Even length list, N = 4 and there will be two swaps
when j=0, swap(0, 3) // Post swap state: D B C A
when j=1, swap(1, 2) // Post swap state: D C B A
Swapping applies to data only, not to pointers, and there might be any sanity checks missed, but you got the idea.
list_t *reverse(list_t *a)
{
list_t *progress = NULL;
while(a)
{
list_t *b; //b is only a temporary variable (don't bother focusing on it)
b = a->next;
a->next = progress; // Because a->next is assigned to another value,
// we must first save a->next to a different
// variable (to be able to use it later)
progress = a; // progress is initially NULL (so a->next = NULL
// (because it is the new last element in the list))
a = b; // We set a to b (the value we saved earlier, what
// a->next was before it became NULL)
/*
Now, at the next iteration, progress will equal a, and a will equal b.
So, when I assign a->next = progress, I really say, b->next = a.
and so what we get is: b->a->NULL.
Maybe that gives you an idea of the picture?
What is important here is:
progress = a
and
a = b
Because that determines what a->next will equal:
c->b->a->0
a's next is set to 0
b's next is set to a
c's next is set to b
*/
}
return progress;
}
The basic idea is to detach the head node from the first list and attach it to the head of a second list. Keep repeating until the first list is empty.
Pseudocode:
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
t = X.next
X.next = Y
Y = X
X = t
ENDWHILE
RETURN Y
ENDfunction
If you wish to leave the original list undisturbed then you can code a copying version recursively with the use of a helper function.
function reverseList(List X) RETURNS List
RETURN reverseListAux(X, null)
ENDfunction
function reverseListAux(List X, List Y) RETURNS List
IF X = null THEN
RETURN Y
ELSE
RETURN reverseListAux(X.next, makeNode(X.data, Y))
ENDfunction
Note that the helper function is tail recursive. This means that you can create a copying reversal using iteration.
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
Y = makeNode(x.data, Y)
X = X.next
ENDWHILE
RETURN Y
ENDfunction
Reversing a singly-linked list using iteration:
current = head // Point the current pointer to the head of the linked list
while(current != NULL)
{
forward = current->link; // Point to the next node
fforward = forward->link; // Point the next node to next node
fforward->link = forward; // 1->2->3,,,,,,,,,this will point node 3 to node 2
forward->link = current; // This will point node 2 to node 1
if(current == head)
current->link = NULL; // If the current pointer is the head pointer it should point to NULL while reversing
current = current->link; // Traversing the list
}
head = current; // Make the current pointer the head pointer
Implementation of a singly-linked list reversal function:
struct Node
{
int data;
struct Node* link;
}
Node* head = NULL;
void reverseList()
{
Node* previous, *current, *next;
previous = NULL;
current = head;
while(current != NULL)
{
next = current-> link;
current->link = previous;
previous = current;
current = next;
}
head = previous;
}
Here is a simple function to reverse a singly linked list
// Defining Node structure
public class Node {
int value;
Node next;
public Node(int val) {
this.value=val;
}
}
public LinkedList reverse(LinkedList list) {
if(list==null) {
return list;
}
Node current=list.head;
Node previous=null;
Node next;
while(current!=null) {
next=current.next;
current.next=previous;
previous=current;
current=next;
}
list.head=previous;
return list;
}
For better understanding, you can watch this video https://youtu.be/6SYVz-pnVwg
If you want to use recursion:
class Solution {
ListNode root=null;
ListNode helper(ListNode head)
{
if (head.next==null)
{ root= head;
return head;}
helper (head.next).next=head;
head.next=null;
return head;
}
public ListNode reverseList(ListNode head) {
if (head==null)
{
return head;
}
helper(head);
return root;
}
}
public void reverseOrder() {
if(head == null) {
System.out.println("list is empty");
}
else {
Node cn = head;
int count = 0;
while (cn != null) {
count++;
cn = cn.next;
}
Node temp;
for(int i = 1; i<=count; i++) {
temp = head;
for(int j = i; j<count; j++) {
temp = temp.next;
}
System.out.print(temp.data+" ->");
}
System.out.print("null");
}
}

Categories