Algorithm [3] prefix tree, linked list related topics

Prefix tree, linked list related topics

trie

  • Prefix tree is also named dictionary tree, word lookup tree, Trie tree, multi-channel tree structure, and hash efficiency. It is a multi-tree structure for fast retrieval. It is mostly used for word frequency search or fuzzy query.
  • The query is only related to the sample length, not the sample size.
  • 1) In a single string, characters from front to back are added to - Multi fork tree
    2) Characters are placed on the road, and there are exclusive data items on the node (commonly pass and end values)
    3) All samples are added in this way. If there is no road, create a new one, and if there is a road, reuse it
    4) The pass value of the node along the way increases by 1, and the end value of the node at the end of each string increases by 1
    You can complete prefix related queries

/pic:mw://20f0c6edb22084fc2a039334fc5f7972

pass is the number of passes, and end is the number of times that the current element ends

The cost of building this tree is O (N)

public class Code_01_TrieTree {	
	public static class TrieNode {
		public int path;
		public int end;
		public TrieNode[] nexts;

		public TrieNode() {
			path = 0;   //How many nodes have arrived
			end = 0;    //How many strings end with this node
			nexts = new TrieNode[26];  //The path to the child node. If the scope given by the topic is uncertain, use map
		}
	}

	public static class Trie {
		private TrieNode root;

		public Trie() {
			//Prepare a header node
			root = new TrieNode();
		}

		//Insert a word
		public void insert(String word) {
			if (word == null) {
				return;
			}
			char[] chs = word.toCharArray();
			TrieNode node = root;
			int index = 0;
			for (int i = 0; i < chs.length; i++) {
				index = chs[i] - 'a';
				if (node.nexts[index] == null) {
					node.nexts[index] = new TrieNode();
				}
				node = node.nexts[index];
				node.path++;
			}
			node.end++;
		}

		//Delete the word from the structure
		public void delete(String word) {
			if (search(word) != 0) {
				char[] chs = word.toCharArray();
				TrieNode node = root;
				int index = 0;
				for (int i = 0; i < chs.length; i++) {
					index = chs[i] - 'a';
					if (--node.nexts[index].path == 0) {
						//If a node after - 1 = = 0, it means that the node after this node is also after - 1 = = 0, so directly = null.
						node.nexts[index] = null;
						return;
					}
					node = node.nexts[index];
				}
				node.end--;
			}
		}

		//Find a word and insert it several times
		public int search(String word) {
			if (word == null) {
				return 0;
			}
			char[] chs = word.toCharArray();
			TrieNode node = root;
			int index = 0;
			for (int i = 0; i < chs.length; i++) {
				index = chs[i] - 'a';
				if (node.nexts[index] == null) {
					return 0;
				}
				node = node.nexts[index];
			}
			return node.end;
		}


		//Check the number of prefixes in a string
		public int prefixNumber(String pre) {
			if (pre == null) {
				return 0;
			}
			char[] chs = pre.toCharArray();
			TrieNode node = root;
			int index = 0;
			for (int i = 0; i < chs.length; i++) {
				index = chs[i] - 'a';
				if (node.nexts[index] == null) {
					return 0;
				}
				node = node.nexts[index];
			}
			return node.path;
		}
	}

	public static void main(String[] args) {
		Trie trie = new Trie();
		System.out.println(trie.search("zuo"));
		trie.insert("zuo");
		System.out.println(trie.search("zuo"));
		trie.delete("zuo");
		System.out.println(trie.search("zuo"));
		trie.insert("zuo");
		trie.insert("zuo");
		trie.delete("zuo");
		System.out.println(trie.search("zuo"));
		trie.delete("zuo");
		System.out.println(trie.search("zuo"));
		trie.insert("zuoa");
		trie.insert("zuoac");
		trie.insert("zuoab");
		trie.insert("zuoad");
		trie.delete("zuoa");
		System.out.println(trie.search("zuoa"));
		System.out.println(trie.prefixNumber("zuo"));

	}

}


Linked list

Written examination can not care about space complexity, all for time complexity

In the interview, time complexity is the most important, but save space

:: speed pointer:

1) Enter the chain header node. The odd length returns the midpoint, and the even length returns the upper midpoint

2) Enter the chain header node. The odd length returns the midpoint, and the even length returns the lower midpoint

3) Enter the chain header node. The odd length returns the previous midpoint, and the even length returns the previous midpoint

4) Enter the chain header node. The odd length returns the one before the midpoint, and the even length returns the one before the next midpoint

1) Enter the chain header node. The odd length returns the midpoint, and the even length returns the upper midpoint

public static Node mid0rUpMidNode(Node head) {
    if (head = nu11|| head.next == nu11|| head.next.next = nu1l) {
    return head;
    }
    //
    Node slow = head. next;
    Node fast = head. next. next;
    while (fast.next != nu1l && fast.next.next != nu1l) {
    	slow = slow. next;
    	fast = fast .next .next;
    }
    return slow;
}

if (head == null|| head.next == nu1l) {
	return true;
}
Node n1 =lhead;
Node n2 = head;
while (n2.next != nu1l && n2.next.next != nu1l) { // find mid node
	n1 = n1.next; // n1 ->mid
	n2 = n2. next.next; 1/ n2 -> end 
}
return n1
 


2) Enter the chain header node. The odd length returns the midpoint, and the even length returns the lower midpoint

public static Node mid0rDownMidNode (Node head) {
    if (head == nul1|| head.next = nu1l) {
    	return head; 
    }
    Node slow = head . next;
    Node fast = head . next;
    while (fast.next != nu1l && fast.next.next != nu1l) {
    	slow = slow.next;
    	fast = fast.next .next;
    }
    return slow;
}

3) Enter the chain header node. The odd length returns the previous midpoint, and the even length returns the previous midpoint

public static Node mid0rUpMidPreNode(Node head) {
    if (head = nu11|| head.next == nu11|| head.next.next == nu1l) {
    	return nu1l;
    }
    Node slow = head;
    Node fast = head. next. next;
    while (fast.next != nu1l && fast.next.next != nu11) {
    	slow = slow.next;
    	fast = fast .next .next;
	}
	return slow;
}

4) Enter the chain header node. The odd length returns the one before the midpoint, and the even length returns the one before the next midpoint

public static Node mi d0rUpMidPreNode(Node head) {
    if (head = nu11|| head.next == nu11|| head.next.next == nu1l) {
    return nu1l;
    }
	Node slow = head;
	Node fast = head . next. next;
	while (fast.next != nu1l && fast.next.next != nu1l) {
		slow = slow.next;
		fast = fast .next .next;
	}
    return slow;
}

:: given the head node of a single linked list, please judge whether the linked list is palindrome structure.::

1) The hash table method is particularly simple (pen trial)

2) The method of changing the original linked list needs to pay attention to the boundary (for interview)

Using the stack, first traverse the stack, then traverse it, and compare it with the elements at the top of the stack

Use less space?

The speed pointer finds the midpoint and the upper midpoint

Press the second half of the stack and compare it with the first half again

Constant space?

First, the speed pointer locates the midpoint and the end, and the next pointer of the midpoint points to null

Reverse the pointers in the second half, and then compare the beginning and end in turn. When one pointer points to null, it is a palindrome structure

If one of them is different, it is a non palindrome

Note that before returning the result, you need to return the second half in reverse order

:: divide the unidirectional linked list into the form of small on the left, equal in the middle and large on the right according to a certain value:

1) Put the linked list into the array and do partition on the array

2) Divided into small, medium and large parts, and then string them together (for interview)

public static Node listPartition2(Node head, int pivot) {
Node sH = nu1l; // small head
Node sT = nu1l; // small tail
Node eH = nu1l; // equal head
Node eT = nu1l; // equal tail
Node mH = nu11; // big head !
Node mT = nu1l; // big tail
Node next = nu1l; // save next node
// every node distributed to three lists
while (head != nu1l) {
    next = head.next;
    head.next = nu1l;
    if (head.value < pivot) {
        if (sH == null) {
            sH = head;
            sT = head;
        } else{
        	sT .next = head;
        	sT = head;
        }else if (head.value == pivot) {
        	if (eH == nu11) {
        		eH = head;
        		eT = head;
        	} else {
        		eT.next = head; 
        		eT = head;
        	}
        }
        head= next;
	}
    /Xinba in xiaori area, even equal to<The head of the domain, wait for the regional huabalian people to open<Header of domain
    if (sT != null) { //If there is a small field
    	sT .next = eH;
    	eT= eT==null?sT:eT;//Whoever connects the head larger than the area becomes eT
    }
    // The if above, whether it's gone or not, et
    // all reconnect
    if (eT != null) { //If it is less than the domain and equal gate < gauge, there is not none
    	eT .next = mH;
    }
    	returnsH!=null?sH:(eH!=nu1l?eH:mH);

}

Copy linked list with special pointer

-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 node structure of the single linked list. rand may point to any node in the linked list or mull
Given the head node of an acyclic single linked list composed of ndoe node types, please implement a function to copy the linked list and return the head node of the copied new linked list.
[required]
Time complexity ON). Additional space complexity O(1)

/pic:mw://03ccf88fcbe09ad4d166dd62401cea8e

Create map

In the first traversal, key is the old node and value is the new node

Traverse the linked list for the second time, find the new node from the old node, and assign the rand pointer to the new node

Finally, return to the new node

public static Node copyListWi thRand1(Node head) {
    HashMap<Node, Node> map = new HashMap<Node, Node>();
    Node cur = head;
    while (cur != nu1l) {
        map.put(cur, new Node(cur .value));
        cur = cur .next ;
    }
    cur = head;
    while (cur != nu1l) {
        .//cur seven
        // map.get(cur)
        map.get(cur).next = map. get(cur . next);
        map. get(cur).rand = map.get(cur.rand);
        cur = cur .next;
    }
    return map. get(head);
}

:: copy without hash table:

For the first traversal, create a new node and insert it behind the old node

Set the rand pointer for the second traversal,

If the rand of 1 points to - > 3

Then the copy node of 3 is behind 3

Point the rand pointer of the copy node of 1 to the next node of 3

Finally, the copied nodes are concatenated to return to their head nodes

/pic:mw://ffca72bcc8cf741c73cc9a71ba8edd2b

public static Node copyListWithRand2(Node head) {
    if (head == nu1l) {
	    return null;
    }
    Node cur = head;
    Node next = null;
    // copy node and link to every node
    //1->2
    //1-> 1'->2
    while (cur != nu11) {
    //cur old|
    	next = cur .next;
    	cur .next = new Node(cur .value);
    	cur .next.next = next;
    	cur = next;
    	cur = head;
    }
    	
    Node curCopy = nu1l;
    // set copy node rand
    //1->1'->2->2'
    
    while (cur != nu1l) {
    // cur 2
    // cur.next new copy
    	next = cur .next .next;
    	curCopy = cur . next;
    	curCopy.rand = cur .rand != null ? cur.rand.next : null;
    	cur = next;
    }
    // head head.next
    Node res = head.next; .
    cur = head;
    // split
    while (cur != nu1l) {
    	next = cur .next. next;
    	curCopy = cur .next;
    	cur .next = next;
    	curCopy.next = next != nu1l ? next.next : nu11;
	    cur = next;
    }
    return res;
}

:: return the first node of intersection:

Given two single linked lists that may or may not have rings, the head nodes head1 and 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.
[required]
If the sum of the lengths of the two linked lists is N, the time complexity should reach O(N), and the additional space should be complex
The impurity should reach 0 (1).

:: give a linked list with a ring and find out the node into the ring:

//Find the first entry point of the chain leader. If not bad. This is null
public static Node getLoopNode(Node head) {
    if (head == nu11 | head.next == nu11|| head.next.next == nu11) {
    return nu11;
    }
    //n1 fast n2
    Node n1 = head.next; // n1 -> slow 
    Node n2 = head.next.next; // n2 -> fast
    while (n1 != n2) {
    	if (n2.next == null|| n2.next.next == nu1l) {
    	return nu11;
    	}
    	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;
}

Both linked lists are acyclic

All the nodes in the first linked list are entered into the set, and the nodes in the second linked list are found to be overlapping

No set

Traverse the first linked list, record the last node, and record the length of the linked list (the length is recorded as x)

Traverse the second linked list, record the last node, and record the length of the linked list (the length is recorded as y)

If the two last nodes are different, they do not intersect

x and y

Big ones go first, take x-y steps

Then the two linked lists go together and will meet at the intersecting node

//If the two chain lengths are not bad, drive back the parent node of phase: if you don't want disaster. Drive null
public static Node noLoop(Node head1, Node head2) {
    if (head1 == null |I head2 == null) {
    	return nu11;
    }
    Node cur1 = head1;
    Node cur2 = head2;
    intn=0;
    while (cur1.next != nu1l) {
   	 n++;
   	 cur1 = cur1.next;
    }
    while (cur2.next != nu1l) {
    	n--;
        cur2 = cur2.next;
    }
    if (cur1 != cur2) {
    	return nu1l;
    }
    // n: the value of chain length 1 minus chain length 2
    cur1=n>0?headl:head2;//Who grows, whose head becomes cur1
    cur2 = cur1 == head1 ? head2 : head1; //Who knows, whose head becomes cur2
    while(n1=){
    n--;
    cur1 = cur1.next;
    while (cur1 != cur2) {
    cur1 = cur1.next;
    cur2 = cur2.next;
    }
    return cur1;
}


One has a ring and the other has no ring. In this case, the two linked lists do not intersect

Both have rings

If two linked lists intersect, they must share this ring

There are three situations

If the memory address of loop1 is equal to the memory address of loop2

Is the second case

If loop 1 is not equal to loop 2

Let loop1 go along the loop. If loop2 is not encountered, it is the first case

That is, there is no intersection

If loop2 is encountered, it is the third case

/pic:mw://6cb42ffbc1d73bb795ceb75c932bc96f

1/Two are linked. Return to network No.Two intersecting nodes. If you don't want to hand in the questions null
public static Node bothLoop(Node head1, Node 1oop1, Node head2, Node 1oop2) {
    Node curl = nu1l;
    Node cur2 = null;
    if (loop1 == 1oop2) {
        cur1 = head1 ;
        cur2 = head2;
        intn=0;
        while (cur1 != 1oop1) {
            n++;
            cur1 = cur1.next;
        }
        while (cur2 != 1oop2) {
            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;
        }
    }else {
    cur1 = 1oop1.next;
    while (cur1 != 1oop1) {
        if (cur1 == 1oop2) {
        return loop1;
        }
    cur1 = cur1.next;
    }
    return nu11;
}



Main method

public static Node getIntersectNode (Node head1, Node head2) {
    if (head1 = null|| head2 = null) {
    return nu11;
    Node 1oop1 = getLoopNode(head1);
    Node_ 1oop2 = getL oopNode (head2) ;
    if (loop1 == nu11 && loop2 == nu11) {
    	return noloop(head1, head2); 
    }
    if (loop1 != nu1l && loop2 != nu11) {
    	return bothLoop(head1, loop1, head2, 1oop2);
    }
    return null;
}

Can you delete this point on the linked list without giving the head node of the single linked list and only the node you want to delete?

Shake smart

Assign the value of the next node of the deleted node to the deleted node, and then point to the next node of the next node

However, the last node cannot be deleted

Tags: Algorithm linked list

Posted on Fri, 15 Oct 2021 23:19:34 -0400 by artyfarty