Linked list algorithm and common examples

Posted by Joan Collins on Thu, 04 Nov 2021 06:19:00 +0100

Linked list

Brief introduction

Hashtable

  • Hash table can be understood as a collection structure at the use level
  • If there is only key and no accompanying data value, you can use the HashSet structure (called unorderderdedset in C + +)
  • If there are both key s and accompanying data value s, you can use the HashMap structure (called unordered map in C + +)
  • Whether there is accompanying data value or not is the only difference between HashMap and HashSet. The actual structure of the underlying is the same thing
  • Using the operations of put, remove, put and get of the hash table, it can be considered that the time complexity is O(1), but the constant time is relatively large
  • If the basic data is put into the hash table, it is passed internally by value, and the memory occupation is the size of this thing
  • If the hash table is not the basic data, it is passed internally by reference. The memory occupation is the size of the memory address of the hash table

Ordered table

  • The ordered table can be understood as a set structure at the use level
  • If there is only key and no accompanying data value, you can use the TreeSet structure (called OrderedSet in C + +)
  • If there are both key s and accompanying data value s, you can use the TreeMap structure (called OrderedMap in C + +)
  • Whether there is accompanying data value or not is the only difference between TreeMap and TreeSet. The actual structure of the underlying is the same thing
  • The difference between an ordered table and a hash table is that an ordered table organizes key s in order, while a hash table is completely inadequate
  • Red black tree, AVL number, size balance tree and jump table all belong to ordered table structure, but the specific implementation of the bottom layer is different
  • If the basic data is put into the ordered table, it is passed internally by value, and the memory occupation is the size of this thing
  • If the items put into the ordered table are not basic data, a comparator must be provided and passed internally by reference. The memory occupation is the size of the memory address of this item
  • No matter what the underlying implementation is, as long as it is an ordered table, it has the following fixed basic functions and fixed time complexity

Fixed operation

TreeMap<Integer, String> treeMap1 = new TreeMap<>();
treeMap1.put(7, "I'm 7");
treeMap1.put(5, "I'm 5");
treeMap1.put(4, "I'm 4");
treeMap1.put(3, "I'm 3");
treeMap1.put(9, "I'm 9");
treeMap1.put(2, "I'm 2");
System.out.println(treeMap1.containsKey(5));
System.out.println(treeMap1.get(5));
System.out.println(treeMap1.firstKey() + ", My youngest");
System.out.println(treeMap1.lastKey() + ", My biggest");
System.out.println(treeMap1.floorKey(8) + ", All in table<=8 Of the numbers, I'm closest to 8");
System.out.println(treeMap1.ceilingKey(8) + ", All in table>=8 Of the numbers, I'm closest to 8");
System.out.println(treeMap1.floorKey(7) + ", All in table<=7 Of the numbers, I'm closest to 7");
System.out.println(treeMap1.ceilingKey(7) + ", All in table>=7 Of the numbers, I'm closest to 7");
treeMap1.remove(5);
System.out.println(treeMap1.get(5) + ", If you delete it, it's gone");

Single linked list, double linked list

Node structure of single linked list

Class Node<V> {
    V value;
    Node next;
}

Node structure of double linked list

Class Node<V>{
    V value;
    Node next;
    Node last;
}

Reverse linked list

Reverse order

Note whether to add the return value

If there is a header change operation, there must be a return value. If not, it can be defined as void type.

Print the common part of two ordered linked lists

Who is small, who moves, prints equally, and moves together until it exceeds.

Methodology of linked list problem solving in interview

  • In the written examination, everything is for the sake of time complexity, and don't care too much about space complexity
  • During the interview, try to find the most space-saving method

skill:

1) Additional data structure records (hash table, etc.)

2) Speed pointer

Examples

Question 1

Given the head node of a single linked list, please judge whether the linked list is palindrome structure

Time complexity O(N), additional space complexity O(1)

  • Method 1

Put it on the stack and compare the popped one with the original one. If each step is the same, it means palindrome. Otherwise it's not palindrome

  • Method 2

Only put the things on the right into the stack. Compare and know that all the things in the stack pop up. If they are the same, it means palindromes. Can save space

(fast and slow pointer) this should be written well

  • Method 3

Not applicable to other data structures.

Use two pointers to move from two directions to the center and compare to the center.

Question 2

The single linked list is divided into the form of small on the left, equal in the middle and large on the right according to a certain value

  • Method 1

Put it into the array, perform partition, and then string it into a linked list

  • Method 2

Define 6 variables

Head and tail SH ST smaller than area

Equal to the head and tail EH ET of the area

Head and tail BH BT larger than area

Be sure to discuss boundaries because there may be no value for a region

public static Node listPartition2(Node head, int pivot) {
   Node sH = null; // small head
   Node sT = null; // small tail
   Node eH = null; // equal head
   Node eT = null; // equal tail
   Node bH = null; // big head
   Node bT = null; // big tail
   Node next = null; // save next node
   // every node distributed to three lists
   while (head != null) {
      next = head.next;
      head.next = null;
      if (head.value < pivot) {
         if (sH == null) {
            sH = head;
            sT = head;
         } else {
            sT.next = head;
            sT = head;
         }
      } else if (head.value == pivot) {
         if (eH == null) {
            eH = head;
            eT = head;
         } else {
            eT.next = head;
            eT = head;
         }
      } else {
         if (bH == null) {
            bH = head;
            bT = head;
         } else {
            bT.next = head;
            bT = head;
         }
      }
      head = next;
   }
   // small and equal reconnect
   if (sT != null) {  //If there is an area smaller than
      sT.next = eH;
      eT = eT == null ? sT : eT; //Next, whoever connects the head larger than the area will become eT
   }
   //if above, whether running or not, eT
   // all reconnect
   if (eT != null) {  //If the smaller than area and the equal and area are not all available
      eT.next = bH;
   }
   return sH != null ? sH : eH != null ? eH : bH;
}
Question 3

A special single linked list node class is described below

class Node {
int value;
Node next;
Node rand;
Node(int val) {
value = val;
}
}

rand pointer is a new pointer in the single linked list Node structure. rand may point to any Node in the linked list or null. Given the head Node of an acyclic single linked list composed of Node types, please implement a function to copy the linked list and return the head Node of the copied new linked list.

  • Method 1

Hash table map

Key - > node type old node, value - > node type new node

Find out the node pointed to by the node through the Map, and then set the node pointed to by the pointer for each copied node.

  • Method 2

Do not use hash table

1) The generated clone node is hung on the next node of the old node

2) Then the rand point of the new node is the next point of the old node

3) On next, take out the clone node

Question 4

Given two single linked lists that may or may not have rings, head node head1 and head node head2. Please implement a function. If two linked lists intersect, please return the first node of the intersection. If it does not intersect, null is returned.

Each node of the single linked list has only one next, so it is impossible to go out of the ring after it is formed. That is, there is only one chain on the ring

  • How to find the first ring entry node (first judge whether the linked list has a ring)
  1. (set a hash table)

At each step, put the values in the linked list into the hash table. When the first node with the same address is encountered, this node is the first ring in node

  1. (fast and slow pointer method)

Set two pointers, one node at a time (slow pointer) and two nodes at a time (fast pointer). When they meet, the fast pointer returns to the first node at the beginning and becomes a step pointer, and then the node where the two pointers meet again is the first entry point.

public static Node getLoopNode(Node head) {
   if (head == null || head.next == null || head.next.next == null) {
      return null;
   }
   Node n1 = head.next; // n1 -> slow
   Node n2 = head.next.next; // n2 -> fast
   while (n1 != n2) {
      if (n2.next == null || n2.next.next == null) {
         return null;
      }
      n2 = n2.next.next;
      n1 = n1.next;
   }
   n2 = head; // n2 -> walk again from head
   while (n1 != n2) {
      n1 = n1.next;
      n2 = n2.next;
   }
   return n1;
}
  • Acyclic case

Each node of the single linked list has only one next, so once there is an intersection, the next parts must be shared.

Traverse the first linked list to know the last node, which is counted as end1 and length length1

Traverse the second linked list. The last one is counted as end2 and the length is length2

First judge whether end1 and end2 memories are equal. If they are not equal, there must be no intersection.

Then the long linked list takes the difference step first, and then the two linked lists go together. The meeting node is the first intersection node.

public static Node noLoop(Node head1, Node head2) {
   if (head1 == null || head2 == null) {
      return null;
   }
   Node cur1 = head1;
   Node cur2 = head2;
   int n = 0;
   while (cur1.next != null) {
      n++;
      cur1 = cur1.next;
   }
   while (cur2.next != null) {
      n--;
      cur2 = cur2.next;
   }
   if (cur1 != cur2) {
      return null;
   }
   //n is the length of linked list 1 minus the length of linked list 2
   cur1 = n > 0 ? head1 : head2;   //Who grows, whose head becomes cur1
   cur2 = cur1 == head1 ? head2 : head1;  //Short to cur2
   n = Math.abs(n);
   while (n != 0) {
      n--;
      cur1 = cur1.next;  //Long go first
   }
   while (cur1 != cur2) {
      cur1 = cur1.next;
      cur2 = cur2.next;
   }            //Walking together, meeting is the intersection node
   return cur1;
}

It is impossible to have a ring, an acyclic, but also intersect

  • There are rings
  1. Each has a ring and does not intersect

If there is a ring and the addresses of the nodes entering the ring are different, loop1 continues to walk once. If loop2 is not encountered, it indicates that there is no intersection. Return null after so long

  1. The ring in node is the same

There are rings, and the end addresses are found to be equal. Then take the first node into the ring as end, and then use the acyclic method to find the first intersection node.

  1. Ring in node is not a

If there is a ring and the addresses of the nodes entering the ring are different, loop1 continues to walk once. If loop2 is encountered, it indicates that it is intersected.

At this time, the loop in node of loop1 or loop2 can be returned, which is the first node of intersection

public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {
   Node cur1 = null;
   Node cur2 = null;
   if (loop1 == loop2) {
      cur1 = head1;
      cur2 = head2;
      int n = 0;
      while (cur1 != loop1) {
         n++;
         cur1 = cur1.next;
      }
      while (cur2 != loop2) {
         n--;
         cur2 = cur2.next;
      }
      cur1 = n > 0 ? head1 : head2;
      cur2 = cur1 == head1 ? head2 : head1;
      n = Math.abs(n);
      while (n != 0) {
         n--;
         cur1 = cur1.next;
      }
      while (cur1 != cur2) {
         cur1 = cur1.next;
         cur2 = cur2.next;
      }
      return cur1;
   } else {
      cur1 = loop1.next;
      while (cur1 != loop1) {
         if (cur1 == loop2) {
            return loop1;
         }
         cur1 = cur1.next;
      }
      return null;
   }
}
public static Node getIntersectNode(Node head1, Node head2) {
   if (head1 == null || head2 == null) {
      return null;
   }
   Node loop1 = getLoopNode(head1);
   Node loop2 = getLoopNode(head2);
   if (loop1 == null && loop2 == null) {
      return noLoop(head1, head2);
   }
   if (loop1 != null && loop2 != null) {
      return bothLoop(head1, loop1, head2, loop2);
   }
   return null;
}

Topics: Algorithm linked list