# Left God algorithm - Basic 04

## A brief introduction to hash table

1) Hash table can be understood as a collection structure at the use level

2) If there is only key and no accompanying data value, you can use the HashSet structure (unorderderdedset in C + +)

3) If there are both key s and accompanying data value s, you can use the HashMap structure (unordered map in C + +)

4) Whether there is accompanying data or not is the only difference between HashMap and HashSet. The actual structure of the underlying is the same thing

5) Using the operations of hash table put, remove, put and get, it can be considered that the time complexity is O(1), but the constant time is relatively large

6) If the hash table is a basic type, it is internally passed by value, and the memory occupation is the size of this thing

7) If the hash table is not the basic type, it is passed internally by reference. The memory occupation is the size of the memory address of the hash table

## A brief introduction to ordered tables

1) The ordered table can be understood as a set structure at the use level

2) If there is only key and no accompanying data value, you can use the TreeSet structure (called orderedset in C + +)

3) If there are both key s and accompanying data value s, you can use the TreeMap structure (called orderedmap in C + +)

4) Whether there is accompanying data or not is the only difference between TreeSet and TreeMap. The actual structure of the underlying is the same thing

5) The difference between an ordered table and a hash table is that an ordered table organizes key s in order, while a hash table does not organize at all

5) Red black tree, AVL tree, size balance tree and jump table all belong to ordered table structure, but the specific implementation of the bottom layer is different

6) If the items put into the ordered table are basic types, they are passed internally by value, and the memory occupation is the size of this item

7) If the object placed in the ordered table is not a basic type, a comparator must be provided. It is passed internally by reference. The memory occupation is the size of the object's memory address

8) 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 of ordered table

1) void put(K key, V value): add a (key, value) record to the table, or update the record of key to value.

2) V get(K key): query value according to the given key and return it.

3) void remove(K key): removes the record of the key.

4) boolean containsKey(K key): ask whether there is a record about the key.

5) K firstKey(): returns the leftmost (smallest) of the sorting results of all key values.

6) K lastKey(): returns the rightmost (largest) sorting result of all key values.

7) K floatkey (k key): if a key has been stored in the table, the key is returned; Otherwise, it returns the previous key in the sorting results of all key values. Returns the maximum value of < = key

8) K ceilingKey(K key): if a key has been stored in the table, the key is returned; Otherwise, the last key in the sorting results of all key values is returned. Returns the minimum value of > = key

All the above operation time complexity is O(logN), and N is the number of records contained in the ordered table

```public static class Node {
public int value;
public Node next;

public Node(int val) {
value = val;
}
}

public static class NodeComparator implements Comparator<Node> {

@Override
public int compare(Node o1, Node o2) {
return o1.value - o2.value;
}

}

public static void main(String[] args) {
Node nodeA = null;
Node nodeB = null;
Node nodeC = null;

// The key of hashSet1 is the basic type - > int type
HashSet<Integer> hashSet1 = new HashSet<>();
System.out.println(hashSet1.contains(3));
hashSet1.remove(3);
System.out.println(hashSet1.contains(3));
System.out.println("========1=========");

// The key of hashSet2 is a non basic type - > node type
nodeA = new Node(1);
nodeB = new Node(1);
HashSet<Node> hashSet2 = new HashSet<>();
System.out.println(hashSet2.contains(nodeA));
System.out.println(hashSet2.contains(nodeB));
hashSet2.remove(nodeA);
System.out.println(hashSet2.contains(nodeA));
System.out.println("========2=========");

// The key of hashMap1 is the basic type - > string type
HashMap<String, Integer> hashMap1 = new HashMap<>();
String str1 = "key";
String str2 = "key";
hashMap1.put(str1, 1);
System.out.println(hashMap1.containsKey(str1));
System.out.println(hashMap1.containsKey(str2));
System.out.println(hashMap1.get(str1));
System.out.println(hashMap1.get(str2));

hashMap1.put(str2, 2);
System.out.println(hashMap1.containsKey(str1));
System.out.println(hashMap1.containsKey(str2));
System.out.println(hashMap1.get(str1));
System.out.println(hashMap1.get(str2));

hashMap1.remove(str1);
System.out.println(hashMap1.containsKey(str1));
System.out.println(hashMap1.containsKey(str2));
System.out.println("========3=========");

// The key of hashMap2 is non basic type - > node type
nodeA = new Node(1);
nodeB = new Node(1);
HashMap<Node, String> hashMap2 = new HashMap<>();
hashMap2.put(nodeA, "A node");
System.out.println(hashMap2.containsKey(nodeA));
System.out.println(hashMap2.containsKey(nodeB));
System.out.println(hashMap2.get(nodeA));
System.out.println(hashMap2.get(nodeB));
hashMap2.put(nodeB, "B node");
System.out.println(hashMap2.containsKey(nodeA));
System.out.println(hashMap2.containsKey(nodeB));
System.out.println(hashMap2.get(nodeA));
System.out.println(hashMap2.get(nodeB));
System.out.println("========4=========");

// The key of treeSet is non basic type - > node type
nodeA = new Node(5);
nodeB = new Node(3);
nodeC = new Node(7);

TreeSet<Node> treeSet = new TreeSet<>();
// The following code will report an error because no comparator of Node type is provided
try {
} catch (Exception e) {
System.out.println("Error message:" + e.getMessage());
}

treeSet = new TreeSet<>(new NodeComparator());
// The following code is OK because a Node type comparator is provided
try {
System.out.println("This time, all nodes have joined");
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("========5=========");

// Display common operations of ordered table
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));
//Sort by comparator
System.out.println(treeMap1.firstKey() + ", My youngest");
System.out.println(treeMap1.lastKey() + ", My biggest");
//floorKey ceilingKey
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");
System.out.println("========6=========");

}
```

### Node structure of single linked list

```class Node<V>{
V value;
Node next;
}
```

The chain formed by connecting the nodes of the above structure in turn is called single linked list structure.

### Node structure of double linked list

```class Node<V>{
V value;
Node next;
Node last;
}
```

The chain formed by connecting the nodes of the above structure in turn is called double linked list structure.

#### Reverse one-way and two-way linked lists

[title] realize the functions of reversing one-way linked list and reversing two-way linked list respectively

[requirement] if the length of the linked list is N, the time complexity is O(N) and the additional space complexity is

O(1)

```    //Unidirectional linked list node
public static class Node {
public int value;
public Node next;

public Node(int data) {
this.value = data;
}
}

public static Node myReverseList(Node head) {
Node p = null;
}
return p;
}
public static class DoubleNode {
public int value;
public DoubleNode last;
public DoubleNode next;

public DoubleNode(int data) {
this.value = data;
}
}

public static DoubleNode myReverseList(DoubleNode head) {
DoubleNode p = null;

//    }
//
//    return p;

}
while(p != null) {
DoubleNode t = p.last;
p = t;
}

}

```

#### Print the common part of two ordered linked lists

[requirement] if the sum of the lengths of the two linked lists is N, the time complexity is O(N), and the additional space is complex

The impurity requirement is O(1)

```public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}

//Orderly linked list, traversal, who is younger, who goes back,
//Equal output, and then go together
System.out.print("Common Part: ");
for (; head1 != null && head2 != null ; ) {
}else {
}
}
System.out.println();
}
```

### Methodology of linked list problem solving in interview

1) For the written test, don't care too much about the spatial complexity, all for the time complexity

2) For the interview, time complexity still comes first, but we must find the most space-saving method

Key skills:

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

2) Speed pointer

#### Judge whether a linked list is palindrome structure

[example] 1 - > 2 - > 1, return true; 1 - > 2 - > 2 - > 1, return true; 15 - > 6 - > 15, return true; 1 - > 2 - > 3, return false.

[example] if the length of the linked list is N, the time complexity reaches O(N) and the additional space complexity reaches O(1).

```public static boolean myIsPalindrome1(Node head) {
//Save it on the stack and read it out
Stack<Node> nodes = new Stack<Node>();
while(p != null) {
nodes.push(p);
p = p.next;
}
return true;
}
return false;
}
// need n extra space
public static boolean isPalindrome1(Node head) {
Stack<Node> stack = new Stack<Node>();
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
return false;
}
}
return true;
}

public static boolean myIsPalindrome2(Node head) {
return true;
}
//Store half of the stack, and then traverse the latter half and compare it with the stack. pop
Stack<Node> nodes = new Stack<Node>();
while(p2.next != null && p2.next.next != null) {
p1 = p1.next;
p2 = p2.next.next;
}

}
if (p2.next != null)   //When p2 is not the tail node, let p1 move back, that is, when the number of summary points is even
p1 = p1.next;
//Otherwise, there is no need to move back
while(p1 != null) {
if (p1.value != nodes.pop().value)
return false;
p1 = p1.next;
}
return true;
}
// need n/2 extra space
public static boolean isPalindrome2(Node head) {
return true;
}
while (cur.next != null && cur.next.next != null) {
right = right.next;
cur = cur.next.next;
}
Stack<Node> stack = new Stack<Node>();
//Store the latter half in the stack structure
while (right != null) {
stack.push(right);
right = right.next;
}
//Whether the stack is empty or not is used as the condition, and there is no need to divide the situation
while (!stack.isEmpty()) {
return false;
}
}
return true;
}

public static boolean myIsPalindrome3(Node head) {
return true;
}
while(p2.next != null && p2.next.next != null) {
p1 = p1.next;
p2 = p2.next.next;
}
//p2 to the end, p1 to the middle
p2 = p1.next;
Node p3 = null;
while(p2 != null) {
Node t = null;
t = p2.next;
p2.next = p3;
p3 = p2;
p2 = t;
}
p2 = p3;
//p3 is the head node in reverse order of the latter paragraph
boolean isPalindrome = true;
while(p3!=null) {
isPalindrome = false;
break;
}
p3 = p3.next;
}
p3 = null;
while(p2 != null) {
Node t = null;
t = p2.next;
p2.next = p3;
p3 = p2;
p2 = t;
}
//p3 head of the latter segment
p1.next = p3;
return isPalindrome;
}

// need O(1) extra space
public static boolean isPalindrome3(Node head) {
return true;
}
while (n2.next != null && n2.next.next != null) { // find mid node
n1 = n1.next; // n1 -> mid
n2 = n2.next.next; // n2 -> end
}
n2 = n1.next; // n2 -> right part first node
n1.next = null; // mid.next -> null
Node n3 = null;
while (n2 != null) { // right part convert
n3 = n2.next; // n3 -> save next node
n2.next = n1; // next of right node convert
n1 = n2; // n1 move
n2 = n3; // n2 move
}
n3 = n1; // n3 -> save last node
n2 = head;// n2 -> left first node
boolean res = true;
while (n1 != null && n2 != null) { // check palindrome
if (n1.value != n2.value) {
res = false;
break;
}
n1 = n1.next; // left to mid
n2 = n2.next; // right to mid
}
n1 = n3.next;
n3.next = null;
while (n1 != null) { // recover list
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
```

#### The one-way 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

[title] give the head node of a single linked list, the value type of the node is integer, and then give an integer pivot.

Implement a function to adjust the linked list. The left part of the linked list is all nodes with values less than pivot, the middle part is all nodes with values equal to pivot, and the right part is all nodes with values greater than pivot.

[advanced] the following requirements are added on the basis of realizing the function of the original problem

[requirement] after adjustment, the relative order of all nodes smaller than pivot is the same as before adjustment

[requirement] after adjustment, the relative order of all nodes equal to pivot is the same as before adjustment

[requirement] after adjustment, the relative order of all nodes larger than pivot is the same as before adjustment

[requirement] the time complexity shall reach O(N), and the additional space complexity shall reach O(1).

```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
if (sH == null) {
} else {
}
} else if (head.value == pivot) {
if (eH == null) {
} else {
}
} else {
if (bH == null) {
} else {
}
}
}
// small and equal reconnect
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// all reconnect
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
```

#### Copy linked list with random pointer nodes

[title] 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.

[requirement] time complexity O(N), additional space complexity O(1)

```	//Using hashmap structure, copy the corresponding relationship of key to value, and return get (head) to ok
public static Node myCopyListWithRand1(Node head) {
HashMap<Node, Node> map = new HashMap<Node, Node>();
while (p != null){
map.put(p,new Node(p.value));
p = p.next;
}
while (p != null) {
map.get(p).next = map.get(p.next);
map.get(p).rand = map.get(p.rand);
p = p.next;
}
}
//The copied node follows the original linked list node and is linked to a linked list to correspond the rand relationship to the copied node
public static Node myCopyListWithRand2(Node head) {
return null;
Node t = null;
while (p != null) {
t = p.next;
p.next = new Node(p.value);
p.next.next = t;
p = t;
}
t = p.next;
while (t != null) {
t.rand = p.rand == null ? null : p.rand.next;
if (t.next == null)
break;
p = p.next.next;
t = t.next.next;
}
while (p.next != null ) {
t = p.next;
p.next = t.next;
p = t;
}
}
```

#### A series of problems about the intersection of two single linked lists

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

[requirement] if the sum of the lengths of the two linked lists is N, the time complexity should reach O(N) and the additional space complexity should reach O(1).

```//It can be divided into two cases: all have rings and all have no rings
return null;

if (loop1 == null && loop2 == null) {
}else if (loop1 != null && loop2 !=null){
}
return null;

}
//Ring node found
public static Node myGetLoopNode(Node head) {
return null;
while (fast != slow && fast != null) {
slow = slow.next;
fast = fast.next == null ? null : fast.next.next;
}
if (fast == null)
return null;
fast = null;
while (fast!=slow){
fast = fast == null ? head : fast.next;
slow = slow.next;
}
return fast;
}
//Are acyclic
int s1 = 0;
int s2 = 0;
int ds = 0;
while(p1.next != null) {
p1 = p1.next;
s1++;
}
while(p2.next != null) {
p2 = p2.next;
s2++;
}
if (p1 != p2)  // The tail node is different, and null is returned directly
return null;
ds = Math.abs(s1 - s2);
if (s1 >= s2){
while(ds > 0){
p1 = p1.next;
ds--;
}
}else {
while(ds > 0){
p2 = p2.next;
ds--;
}
}
while (p1 != p2){
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
//There are rings
public static Node myBothLoop(Node head1, Node loop1, Node head2, Node loop2) {
if (loop1 == loop2) {
int s1 = 0;
int s2 = 0;
int ds = 0;
while (p1 != loop1) {
p1 = p1.next;
s1++;
}
while (p2 != loop1) {
p2 = p2.next;
s2++;
}
ds = Math.abs(s1 - s2);
if (s1 >= s2) {
while (ds > 0) {
p1 = p1.next;
ds--;
}
} else {
while (ds > 0) {
p2 = p2.next;
ds--;
}
}
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}else {
Node p1 = loop1;
while (p1 != loop2){
p1 = p1.next;
if (p1 == loop1)
return null;
}
return loop1;
}

}
```

Tags: Algorithm

Posted on Sat, 06 Nov 2021 06:37:58 -0400 by stylezeca