I wrote this solution to the problem mentioned, I am having trouble finding the complexities since I am less familiar with heaps, any suggestion/correction in my complexity analysis would help.
If n is the size of ArrayList
and m is the length of the longest linked list
According to me, the complexities should be as follows
Space Complexity: O(nm) (for heap)
Time Complexity: O(nm) (doubt this one)
public class Solution {
public ListNode mergeKLists(ArrayList<ListNode> a) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for(ListNode node: a) {
while(node != null) {
minHeap.add(node.val);
node = node.next;
}
}
ListNode head = new ListNode(0);
ListNode temp = head;
while(minHeap.size() > 0) {
ListNode newNode = new ListNode(minHeap.poll());
temp.next = newNode;
temp = temp.next;
}
return head.next;
}
}
If you have k sorted lists, and n total elements, then the time complexity of merging the lists is O(n * log(k)). The heap space required is O(k). Here's how it works.
First, create the heap and the head node of each list into it. So rather than a PriorityQueue<Integer>, you'd have a PriorityQueue<ListNode>. You'll have to write a custom comparator, of course, to sort on the value of the ListNode.
Now, when you poll the heap, you get the ListNode at the head of that list. If that node's next is not null, then push next back onto the heap. If the node's next is null, then you're at the end of that list and you don't push anything back onto the heap.
It looks something like:
ListNode head = new ListNode(0);
ListNode temp = head;
for each ListNode in a
minHeap.add(a)
while minHeap is not empty
node = minHeap.pop()
if node.next is not null
minHeap.push(node.next)
temp.next = node;
temp = node;
return head.next;
Why each time we create new node p.next so we need to assign null to this.next? isn't always null any way? and which role does it play in LinkedList ?
if we try to print out this.next it will be null before we assign it to null.
System.out.println(this.next);
Result is null
Also if p.next point to the new node why we need to set p = p.next to point to the same node? if the purpose to set tail to p at last, can't we just set tail = p.next which is the last one after for loop is finished.
public class EnkeltLenketListe<T>{
private T value;
private Node<T> next;
private Node(T value, Node<T> next)
{
System.out.println(this.next);
this.next = next;
this.value = value;
}
}
private Node<T> head, tail;
public EnkeltLenketListe(T[] a)
{
this();
int i = 0; for (; i < a.length && a[i] == null; i++);
if (i < a.length)
{
head = new Node<>(a[i], null);
Node<T> p = head;
for (i++; i < a.length; i++)
{
if (a[i] != null)
{
p.next = new Node<>(a[i], null);
p = p.next;
}
}
tail = p;
}
}
Why each time we create new node p.next so we need to assign null to this.next?
while adding and removing a nodes, we have to make sure that nodes don't point to unintended nodes. they might have pointing to some nodes.
why we need to set p = p.next to point to the same node
to locate and maintain your position in the list while you are traversing the list, you start from head, and continue to remaining nodes. if p=p.next, how are going to traverse the list?
can't we just set tail = p.next which is the last one after for loop is finished.
No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop. test it by adding the following before tail=p, you should get null
System.out.println(p.next);
Edited:
your list is singly linked list which means every node except the tail should have a pointer to next node, you started with
head = new Node<>(a[i], null);
Node<T> p = head;
in this case p and head are pointing Node 0 see image below. if the next NOde in the array is not null, let see what happens in the for loop
p.next = new Node<>(a[i], null);
p = p.next;
In this case p.next is pointing to Node 1 (see image below), where as p which were pointing to Node 0 is now set to point to Node 1. so both are pointing to 'Node 1`. the last one:
tail = p;
You said that why don't we just tail=p.next? No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop.
read about singly linked list here
Try to use contradiction. If you didn't set p = p.next, in the next iteration of the loop, again you will set the new node to the next position of the previous node. Hence, all the time p is the head and you didn't move the p anymore!
Therefore, you need to move p in each iteration after setting p.next. Indeed, it is a pointer to the last element of the list.
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;
}
}
I need to create a method in java that recursively determines the distance from any given node back to the root. The method returns an integer that shows how many nodes away the specific node is from the root. The node class is given below
Public class Node
{
int data;
node left;
node right;
}
No global variables or attributes allowed, and I cannot modify the node class. I've looked it up and each solution tells me to modify the node class to include a node pointer for a parent node. Any help would be appreciated, thanks!
If you have parent stored in each node, search would require O(log N) operations (in case of balanced tree)--you just walk through parents and count steps until parent == null which means root node.
But without parent field, you need to recursively traverse the whole tree starting from the root, looking for a given node. It requires O(N) operations:
/** Returns the distance between "n" and "current" plus "step"
/* or -1 if "n" not found */
int distance(Node n, Node current, int step) {
int res = -1;
if (n == current) // node found
return step;
if (current.left == null && current.right == null) // leaf node
return -1;
if (current.left != null) // search in left subtree
res = distance(n, current.left, step + 1);
if (res > 0)
return res;
if (current.right != null) // search in right subtree
res = distance(n, current.right, step + 1);
return res;
}
//....
Node root;
Node given;
int dist = distance(given, root, 0); // distance between "root" and "given"
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");
}
}