ctci/02. Linked lists
anebz 6280172289 fix: reordering and fix of small errors 2019-09-19 09:30:43 +02:00
..
hackerrank fix: reordering and fix of small errors 2019-09-19 09:30:43 +02:00
2.1. remove_duplicates.md 2.2. return kth to last 2019-07-29 08:12:01 +02:00
2.2. return_kth_to_last.md fix: reordering and fix of small errors 2019-09-19 09:30:43 +02:00
2.3. delete_middle_node.md 2.3. delete middle node in linked list 2019-07-29 08:12:11 +02:00
2.4. partition_list.md 2.4. partition list 2019-08-02 08:59:55 +02:00
2.5. sum_lists.md 2.5. sum lists 2019-08-02 09:00:05 +02:00
2.6. palindrome.md 2.6. palindrome 2019-08-06 20:27:05 +02:00
2.7. intersection.java Updated exercises and README with ch2 2019-08-09 00:03:49 +02:00
2.7. intersection.md Updated exercises and README with ch2 2019-08-09 00:03:49 +02:00
2.8. loop_detection.md 2.8. loop detection 2019-08-09 00:03:57 +02:00
README.md 2.6. palindrome 2019-08-06 20:27:05 +02:00

README.md

Chapter 2: Linked lists

A linked list is a data structure representing a sequence of nodes. In a single linked list, each node points to the next node in the linked list. A doubly linked list gives each node pointers to both the next node and the previous node.

Lookup time isn't constant because it needs to iterate through K elements, but adding or deleting has constant time.

Creating a LinkedList

class Node {
    Node next = null;
    int data;

    public Node(int d){
        data = d,
    }

    void appendToTail(int d){
        Node end = new Node(d);
        Node n = this;
        while (n.next != null){
            n = n.next
        }
        n.next = end;
    }
}

Node a = new Node(5);
Node b = new Node(7);
a.appendTotail(b);

We access the linked list through a reference to the head Node of the linked list. If multiple objects need a reference to the linked ilst, and then the head changes, some objects might reference the old head. We could implement a LinkedList class wrapping the Node class, and have a single member variable, the head Node. LinkedLists can be singly linked or double linked (linked from left to right or from right to left also).

Deleting an element in a singly linked list

Given a node n, find the previous node prev, and set prev.next = n.next. Remember to check for null pointer and to update the head or tail pointer as necessary.

Node deleteNode(Node head, int d){
    if (head == null) return null;
    Node n = head;

    if (n.data == d){
        return head.next; // moved head, if the node to be deleted is at head
    }

    while (n.next != null){
        if (n.next.data == d){
            n.next = n.next.next;
            return head; // head doesn't change
        }
        n = n.next; // iterate to the next node
    }
    return head;
}

The runner technique

Sometimes two pointers are used, you iterate through the linked list with two pointers simultaneously, with one ahead of the other. The fast pointer might be ahead by a fixed amount, or hopping multiple nodes for each node that the 'slow' node iterates through.

If we have a linked list a1 -> a2 -> an -> b1 -> b2 -> bn and we want to rearrange it to a1 -> b1 -> a2 -> b2 ..., and we don't know how long the list is but we know its length is an even number, we could have one pointer p1 move every two elements for every one move that p2 does. When p1 reaches the end of the list, p2 will be at midpoint. Then, move p1 back to the front and on each iteration, p2 selects an element and inserts it after p1.

Question: then why do we iterate to the end bzw midpoint of the list? Just start rearranging from the very beginning. But we need p2 to reach the end, still that can be done with just p2, no need to move p1 as well.

Recursive problems

Many linked list problems rely on recursion. But remember that recursion techniques take O(n) space and they can be implemented iteratively, but they might be much more complex.

Resources