1, Linked list
2, Queues
3, Stack
1, Linked list
JZ3 printing chain list from end to end
The k last node in JZ14 list
JZ15 reverse list
JZ16 merges two sorted linked lists
Copy of JZ25 complex linked list
JZ26 binary search tree and double linked list
The first common node of two linked lists of JZ36
JZ46 children's game (last remaining number in circle)
The entry node of link in JZ55 list
JZ56 delete duplicate nodes in linked list
The k-th node of JZ62 binary search tree
- Ideas:
It just needs to print out the value of the linked list, so it's not so complicated. When it comes to inversion, you only need to use Stack. - code:
/** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int val) { * this.val = val; * } * } * */ import java.util.ArrayList; import java.util.Stack; public class Solution { public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { //Just return the value in the linked list. Consider using stack ArrayList<Integer> result = new ArrayList<>(); Stack<Integer> stack=new Stack<>(); while( listNode != null){ stack.push(listNode.val); listNode=listNode.next; //Remember to make the node point to the next node after passing the value } while(!stack.isEmpty()){ result.add(stack.pop()); } return result; } }
- Knowledge points:
Guide Package: import java.util.ArrayList ; and import java.util.Stack ;
Note that after using a node, you should point the next node to the current node
- Ideas:
Suppose 6 nodes are 123456, then the penultimate node is actually the fifth positive node, k=2, 5 = 6 + 1-2.
So the code first calculates the length of the list, and then adds 1 minus k, which is the positive node. We are traversing the list, taking this node as the return value. - code:
public ListNode FindKthToTail(ListNode head,int k){ //Suppose 6 nodes, 1 23 4 5 6 the second from the bottom, that is, the fifth positive node, k=2, the fifth positive node //First find the length of the list int size=0; ListNode pHead=head; while(pHead!=null){ size++; pHead=pHead.next; } if(k>size) return null; //Pay attention to judge whether k is out of range else{ int head_num=size+1-k; //6+1-2=5 pHead=head; for(int i=1;i<head_num;i++){ pHead=pHead.next; } return pHead; } }
- Knowledge points:
Pay attention to the code block to find the length of the list.
- Ideas:
Reversing the linked list requires three nodes: the current node head, the previous node pre of the current node and the next node next of the current node. Loop: exchange as long as the current node head is not empty. - code:
public ListNode ReverseList(ListNode head){ //The exchange between three nodes is needed to reverse the linked list ListNode pre=null; ListNode next=null; while(head!=null){//If the head does not reach null, it means that the head is not the last node, and it needs to be exchanged all the time next=head.next;//First, the head points to the current node, so when the head is the head node at the beginning, pre=null is OK, but next should not be null, so first assign a value to next head.next=pre;//head is the current node. To reverse the linked list, the next node of the current node should be the previous node, that is, pre pre=head; //Even after the first two lines of code are converted, the next step is to move the node. If all the nodes are moved backward, pre should be the current node just now head=next; //next should assign a value to the current node } return pre; //The final return should be pre, because when the head points to the last node, the head is not null. After the loop is executed, the head points to null, // In judgment, it is found that the cycle conditions are not satisfied, // But at this time, the head points to null, and pre is the last node, which is the current head node, so pre is returned }
- Knowledge points:
Note that the exchange process in the loop requires three nodes to exchange;
Note the last return value;
- Ideas:
First, compare the head nodes of two linked lists, list1 and list2. Suppose that the head nodes of list1 are small, then assign list1 to list. Note that since the first assumption is that list is null, the whole list1 should be assigned to list, not just val, which is invalid. Then modify the next value of list, and use recursion to compare the remaining nodes of list1 and the nodes of list2. - code:
public ListNode Merge(ListNode list1,ListNode list2){ ListNode list=null; if(list1==null){ return list2; }else if(list2==null){ return list1; } if(list1.val<=list2.val){ // list.val=list1.val; list=list1; // It's wrong to write as above, because the list is null at the beginning, so there is no val, //You need to give list1 to list directly, and then modify the value of next list.next=Merge(list1.next,list2); } if(list1.val>list2.val){ // list.val=list2.val; list=list2; // It's wrong to write as above, because the list is null at the beginning, so there is no val, //You need to give list2 directly to the list, and then change the value of next list.next=Merge(list1,list2.next); } return list; }25. Copy complex linked list [linked list] [HashMap]
- Ideas:
First of all, we need to create a new linked list. This new linked list should be connected with the original linked list. We choose to use hashmap map to connect the old and new linked lists. The new linked list is stored in the label value. Then connect the new linked list, that is, store the values of next and random. - code:
//To copy a new list, you must first create a new list, and the new list must be linked with the original list public RandomListNode Clone(RandomListNode pHead){ //First, we use hashmap to establish the relationship between the original list and the new list HashMap<RandomListNode,RandomListNode> map=new HashMap<>();//Establish the relationship between the original list and the new list RandomListNode p1=pHead;////The corresponding node relationship used to create the new and old linked list while(p1!=null){ map.put(p1,new RandomListNode(p1.label)); //Save label s one by one into the new list p1=p1.next; }//So far, the new linked list and the old linked list relationship are created successfully, but the new linked list only has the label value, and next and random are both null RandomListNode p2=pHead;// Used to store next and random pointers while(p2!=null){ //Since the next of the last node may be null, you need to judge whether it is the last node //But random has no null nodes, so there is no need to judge if(p2.next!=null){ map.get(p2).next=map.get(p2.next); //map.get(p2) indicates the node that gets the new linked list. The next value of this node should store the next node, // The next node should be the second node of the new RandomListNode just created }else{ map.get(p2).next=null; } map.get(p2).random=map.get(p2.random); p2=p2.next; } return map.get(pHead); }26. Binary search tree and bidirectional linked list [binary tree], [linked list], [ArrayList]
- Ideas:
In a binary search tree, the values of all nodes in the left subtree are less than the values of the root nodes, the values of all nodes in the right subtree are greater than the values of the root nodes, and the values of left < root < right.
To turn a binary search tree into a sorted list is actually to traverse the middle order, and then string the results of the middle order.
Middle order traversal reference blog - code:
ArrayList<TreeNode> list=new ArrayList<>(); public TreeNode Convert(TreeNode pRootOfTree){ if(pRootOfTree == null) return null; //Binary search tree, the value of all nodes in the left subtree is less than the value of the root node, the value of all nodes in the right subtree is greater than the value of the root node, left < root < right //Turning a binary search tree into a sorted list is actually the middle order, and then string the results of the middle order Trans(pRootOfTree); //Get a sorted list //2 5 9 connected in series for(int i=0;i<list.size()-1;i++){ list.get(i).right=list.get(i+1);//The right node of the current value should store the next value in the list list.get(i+1).left=list.get(i); //The left of i+1 stores the information of the previous node //In this way, the special first and last nodes are not involved } return list.get(0); } public void Trans(TreeNode pRootOfTree){ if(pRootOfTree==null) return ; else { Trans(pRootOfTree.left); list.add(pRootOfTree); Trans(pRootOfTree.right); } }
- Knowledge points:
When the list is concatenated into a double line list, pay attention to the value of i from 0 to < size-1. This method is very powerful.
- Ideas:
Find the length of two lists, and then let the long list go by one length first. When traversing two linked lists at the same time, the first same node encountered can be used as the return value. - code:
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2){ //Find the length of two linked lists int count1=0; ListNode p1=pHead1; while (p1!=null){ count1++; p1=p1.next; } int count2=0; ListNode p2=pHead2; while (p2!=null){ count2++; p2=p2.next; } //Let the long list take the steps of the difference between two lengths first int sub=count1-count2; p1=pHead1; p2=pHead2; if(sub>0){ //Description chain 1 length for(int i=0;i<sub;i++){ p1=p1.next; } }else { sub=-sub; for (int i=0;i<sub;i++){ p2=p2.next; } } //Two linked lists go together, and the same node is used as the return value while (p1!=null && p2!=null){ if(p1==p2) return p1; p1=p1.next; p2=p2.next; } return null;46. Children's games (the last remaining number in the circle) [array], [cycle], [need to be read carefully]
- Ideas:
Put the element in the list first. As long as the number of elements in the list is greater than 1, the elements must be deleted all the time. The deletion of an element depends on the loop m, which does not delete one element at a time. Therefore, an additional element cur is needed to record the current position, which is cycled from the current position to the next. - code:
public int LastRemaining_Solution(int n, int m){ if(n<1||m<1) return -1; //Pay attention to special situations ArrayList<Integer> list=new ArrayList<>(); for(int i=0;i<n;i++){ list.add(i); } //Save the child's serial number in a list [0 1 2 3 4 5 6] m = 3 int cur=-1; //Point to current pointer while(list.size()>1){ for(int i=0;i<m;i++){//Control the number of loops, and delete one element every time the loop is executed cur++; if(cur==list.size()) cur=0; }//Loop through and delete an element list.remove(cur);//After deleting this element, cur needs to be changed. After deleting 2, it changes to [0 1 3 4 5 6]. cur=2 at this time, but in the next cycle, cur needs to be 2, so it is decremented once cur--; } return list.get(0); }55. Entry node of link in the list
- Ideas:
First, judge whether there is a ring. The two pointers start from the beginning, one step at a time and one step at a time. If there is a ring, then the fast pointer and the slow pointer will meet. If there is no ring, then the fast pointer and the next of the fast pointer will point to null at the same time.
Then judge the number of nodes in the ring. The two pointers just met must be the points in the ring. When the points in the ring return to this point again, the number of nodes in the ring is the number of steps.
Then one pointer starts from the beginning, and the other starts from the number of nodes in the ring. The meeting of the two is the beginning of the ring. - code:
if(pHead == null){ return null; } // To determine whether it is a ring, start with two pointers from the beginning node, slow one at a time, fast two at a time, //If it is a ring, fast will always return to meet slow. If it is not a ring, fast will not meet slow when it comes to the tail node boolean isHuan = false; //Default is not a ring ListNode slow=pHead; ListNode fast=pHead; while(fast!=null && fast.next!=null){ //fast doesn't arrive at the tail node, so it goes all the way back, arrives at the tail node, and doesn't meet, so it's not a ring slow=slow.next; fast=fast.next.next; if(slow == fast){ isHuan = true; break; } } //If it is not a ring, return null if(!isHuan) { return null; }else{ //If it is a ring, then determine the number of nodes in the ring. The node just met must be the node in the ring, //So from this node, the number of steps to return to this node is the number of nodes in the ring int n=1; // fast and slow now refer to the same node, the node that meets fast=fast.next; while(fast!=slow){ fast=fast.next; n++; } //n is the number of nodes in the ring //Find the node entry. One node starts from the beginning, the other node starts from the node length. The node that meets is the ring entry slow = pHead; fast = pHead; for(int i=0;i<n;i++){ fast=fast.next; } //Then each node takes one step until it meets, which is the entrance of the node while(slow!=fast){ slow=slow.next; fast=fast.next; } } return fast; }56. Delete duplicate nodes in the list
-
Ideas:
It is very important to note that when looping the list, the last node should be noted. When p points to the last node, P's next is null. If you use p.next!=null as the judgment condition, it is OK, but if you write P later next.val An exception will occur, because there is no value of Val, so sometimes we consider to judge while (p.next!=null)The duplicate elements are first stored in the set set. Then, first process the head node to see if it is a repeating element. Then traverse the original linked list, take out the elements in the original linked list one by one, and see if there is one in the set. If there is one, we don't save this element in the new linked list. Skip this element. If there is no such element in the set, we need this element in the new linked list.
-
code:
public ListNode deleteDuplication(ListNode pHead){ HashSet<Integer> set=new HashSet<>(); ListNode p=pHead; while (p.next!=null){ //By the time of the last pointer, p.next is null, because P next.val , null pointer has no Val, so only p.next can be written here if(p.val == p.next.val) set.add(p.val); p=p.next; } //Regroup a linked list as the return value, first handle the header node separately while (pHead!=null && set.contains(pHead.val)){ pHead=pHead.next; } if(pHead==null) return null; ListNode pre=pHead; ListNode cur=pHead.next; while (cur!=null){ if(set.contains(cur.val)){ pre.next=cur.next; cur=cur.next; }else{ pre=pre.next; cur=cur.next; } } return pHead; }62. The k-th node of binary search tree
- Ideas:
Binary search tree, if you want to program the sorted list, you can directly traverse it in the middle order.
Then find the k-th node in the linked list. Note that the linked list has the function of size, and you don't need to write this function yourself. - code:
ArrayList<TreeNode> list=new ArrayList<>(); TreeNode KthNode(TreeNode pRoot, int k){ Trans(pRoot); if(k>=1 && list.size()>=k) { return list.get(k-1); //The size of the linked list can be directly used by functions without traversing } return null; } public void Trans(TreeNode root){ //Middle order ergodic if(root == null) return ; Trans(root.left); list.add(root); Trans(root.right); }
2, Queues
JZ5 uses two stacks to implement queues
JZ22 print binary tree from top to bottom
JZ59 print binary tree in zigzag order
JZ60 print binary tree into multiple lines
JZ61 serialized binary tree
-
Ideas:
Stack is first in first out, queue is first in first out. Two stacks are used to implement queue, queue and queue functions.
To join the team, there is nothing to say. You can just put in the element directly, and you don't need to return the value, so you can directly save it in stack1.
When leaving the team, we should pay attention to the first in first out, so we need to import the element from stack1 to stack2, and then tsack2 leaves the team. The element leaving the team is the top element in stack2, which is the most advanced element in the stack.
It should also be noted that after leaving the team, it is convenient for other elements to enter the team next time, which is to enter stack1. Therefore, after leaving the team, the elements in stack2 need to be put back into stack1. -
code:
//Problem 5: using two stacks to implement queues Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); public void push(int node) { stack1.push(node); //To join the team, there's nothing to say. Just put in the element directly, and you don't need to return the value, so you can save it in stack1 directly } public int pop() { //When leaving the team, we should pay attention to the first in first out, so we need to import the elements from stack1 to stack2, and then leave the team. The element of leaving the team is the top element in stack2 //It should also be noted that after leaving the team, it is convenient to enter the team next time, which is to enter stack1. Therefore, after leaving the team, you need to put the elements in stack2 back into stack1 while(!stack1.isEmpty()){ stack2.push(stack1.pop()); } int result= stack2.pop(); while(!stack2.isEmpty()){ stack1.push(stack2.pop()); } return result; }
- Knowledge points:
Two queues are added to realize the stack:
There's nothing to say about the push element. It's the same as the stack operation. First, use a queue to store the pushed element.
When going out of the stack, we need to pay attention to the fact that the queue in q1, the queue in 123 and the stack out should be three, so we can go out of the queue one by one and store the elements that are not the top level in q2.
After 3, the elements in q2 will be saved back to q1 to facilitate the next entry of other elements
//Two queue implementation stacks Queue<Integer> queue1=new LinkedList<>(); Queue<Integer> queue2=new LinkedList<>(); public void push(int node) {//There's nothing to say about the pressing element. It's the same as the stack operation. First, use a queue to store the pressed element queue1.offer(node); } public int pop(){ //When going out of the stack, we need to pay attention to the fact that the queue in q1, the queue in 123 and the stack out should be three, so we can go out of the queue one by one, and store the elements that are not top-level elements in q2, // After 3, the elements in q2 will be saved back to q1 to facilitate the next entry of other elements while (queue1.size()!=1){ queue2.offer(queue1.poll()); } int result=queue1.poll(); while(!queue2.isEmpty()){ queue1.offer(queue2.poll()); } return result; }
I'm not sure whether the code is wrong or the team. Let's check the problem one day.
21. Print binary tree [binary tree], [Print], [queue] from top to bottom- Ideas:
To print a binary tree, you need to save the root node in the queue first, and then loop as long as the queue is not empty. Then, the nodes in the queue will emerge one by one, the values will be stored in the list, and then the left and right child nodes will be stored in the queue in turn. - code:
//Print binary tree from top to bottom //Printing linked list needs queue public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList<Integer> list=new ArrayList<>(); if(root==null) return list; Queue<TreeNode> queue=new LinkedList<>(); queue.offer(root); while(!queue.isEmpty()){ TreeNode temp=queue.poll(); list.add(temp.val); // queue.offer(temp.left); // queue.offer(temp.right); // It's wrong to write like this. You must first judge whether it's empty and then offer value. Otherwise, offer provides null if(temp.left!=null) queue.offer(temp.left); if(temp.right!=null) queue.offer(temp.right); } return list; }59. Print binary trees in zigzag order
- Ideas:
Introduce the parameters of size size and whether to reverse. - code:
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> result = new ArrayList<>(); if(pRoot == null) return result; Queue<TreeNode> q=new LinkedList<TreeNode>(); //Storage node q.offer(pRoot); boolean rev=false;//Reverse save element or not while(!q.isEmpty()){ ArrayList<Integer> list=new ArrayList<>(); int size = q.size(); //Number of queue elements per row for(int i=0;i<size;i++){ TreeNode temp = q.poll(); if(temp == null) continue; if(!rev){ list.add(temp.val); }else{ list.add(0,temp.val); } q.offer(temp.left); //After the value of the element is put in, its node will be put into the queue, //The size of this line has been determined. The value of this line will not be affected when it is sent to the queue. The size of the next line will be determined again q.offer(temp.right); } if(list.size()>0){ //Note that if there is no element in the list, do not store the element, so it needs to be judged result.add(list); } rev = !rev; } return result; }60. Print binary tree into multiple lines
- Ideas:
It is necessary to introduce a size parameter, size of each cycle, and take out the variables in the queue. - code:
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> result = new ArrayList<>(); //The result contains a list if(pRoot == null) return result; Queue<TreeNode> q = new LinkedList<>(); //Used to store nodes in each row, one by one, one by one q.offer(pRoot); while(!q.isEmpty()){ //Only when the queue is not empty can the element be fetched out ArrayList<Integer> list=new ArrayList<>(); //Elements used to store each row //Because the elements of each row are independent, you need to define a size in advance. When fetching an element, you need to take a left and right node to store the element, //So define size in advance and take out the size element int size=q.size(); for(int i=0;i<size;i++){ TreeNode temp=q.poll(); //Take the elements in each row out of the elements in the queue //Since there are not necessarily several nodes in a row, a temporary variable named temp is defined one by one list.add(temp.val); //After the node is taken out, the left and right nodes of this node should be stored in the queue for the next cycle if(temp.left != null) q.offer(temp.left); if(temp.right != null) q.offer(temp.right); } if(!list.isEmpty()){ //If the list is not empty, it will be put in the result result.add(list); } } return result; }61. Serialize binary tree
On the subject of offer
No, I don't understand
3, Stack
JZ20 stack containing min function
Press and pop sequence of JZ21 stack
JZ5 uses two stacks to implement queues
The k-th node of JZ62 binary search tree
- Ideas:
There are two methods: Method 1: Sword refers to the method on offer, which uses an auxiliary stack. Every element stored in the basic stack, the smallest element is stored in the auxiliary stack. Please refer to the analysis in the book for details, The code can refer to the analysis of Wuhan sun Yifeng in the link
Method 2: use the iterator to find the minimum value and return the minimum value. - code:
//Stack containing min function //There are two ways: one is to use the sword finger on the offer book with the help of the auxiliary stack //One is to use iterators //The method of using iterator is relatively simple. First, use the method of iterator: Stack<Integer> stack=new Stack<>(); public void push(int node) { stack.push(node); } public void pop() { stack.pop(); } public int top() { return stack.peek(); } public int min() { //The use of iterators requires a package Guide Iterator<Integer> it =stack.iterator(); int min=stack.peek(); int tmp=0; while (it.hasNext()){ tmp=it.next();//Just once if(min>tmp) min=tmp; } // Iterator<Integer> it =stack.iterator(); // int min=stack.peek(); // while (it.hasNext()){ // if(min>it.next()) min=it.next(); // }/ / error demonstration. Error reason: every use it.next It will be the next element, so it must be problematic to use next multiple times in the loop return min; }
- Knowledge:
The most important thing is the wrong use of the iterator. When the iterator is used again, I made a mistake that I used next multiple times in the loop, but in fact, every time I use next, I use the next element. So when I use next later, I should first assign it to a tmp variable, and then use tmp to calculate.
-
Ideas:
Each time an element is stored in the stack, it will be compared with popA, and the same will pop up, and popA will enter the next element
If the top element of the stack is equal to the first element of popA, you need to stack,
After leaving the stack, it is necessary to continue to judge whether the top element of the stack is equal to the next element of popA,
If the same stack needs to be pushed out, the next round of pushing can only be carried out if it is not, -
code:
public boolean IsPopOrder(int [] pushA,int [] popA){ // For stacks, length is an attribute if(pushA.length == 0 || popA.length== 0 || pushA.length != popA.length){ return false; } int j=0; Stack<Integer> stack=new Stack<>(); for(int i=0;i<pushA.length;i++){ stack.push(pushA[i]); //First, put the elements in the stack to see if you can empty the elements in the stack and return true //Each time an element is stored in the stack, it will be compared with popA, and the same will pop up, and popA will enter the next element //If the top element of the stack is equal to the first element of popA, you need to stack, //After leaving the stack, it is necessary to continue to judge whether the top element of the stack is equal to the next element of popA, //If you want to continue out of the stack if you are equal, you can continue to stack if you are not equal, //So what we need here is a loop to make multiple judgments while(!stack.isEmpty() && stack.peek()==popA[j]){ stack.pop(); j++; } } return stack.isEmpty(); }5. Use two stacks to implement the queue [queue and stack]
-
Ideas:
Stack is first in first out, queue is first in first out. Two stacks are used to implement queue, queue and queue functions.
To join the team, there is nothing to say. You can just put in the element directly, and you don't need to return the value, so you can directly save it in stack1.
When leaving the team, we should pay attention to the first in first out, so we need to import the element from stack1 to stack2, and then tsack2 leaves the team. The element leaving the team is the top element in stack2, which is the most advanced element in the stack.
It should also be noted that after leaving the team, it is convenient for other elements to enter the team next time, which is to enter stack1. Therefore, after leaving the team, the elements in stack2 need to be put back into stack1. -
code:
//Problem 5: using two stacks to implement queues Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); public void push(int node) { stack1.push(node); //To join the team, there's nothing to say. Just put in the element directly, and you don't need to return the value, so you can save it in stack1 directly } public int pop() { //When leaving the team, we should pay attention to the first in first out, so we need to import the elements from stack1 to stack2, and then leave the team. The element of leaving the team is the top element in stack2 //It should also be noted that after leaving the team, it is convenient to enter the team next time, which is to enter stack1. Therefore, after leaving the team, you need to put the elements in stack2 back into stack1 while(!stack1.isEmpty()){ stack2.push(stack1.pop()); } int result= stack2.pop(); while(!stack2.isEmpty()){ stack1.push(stack2.pop()); } return result; }
- Knowledge points:
Two queues are added to realize the stack:
There's nothing to say about the push element. It's the same as the stack operation. First, use a queue to store the pushed element.
When going out of the stack, we need to pay attention to the fact that the queue in q1, the queue in 123 and the stack out should be three, so we can go out of the queue one by one and store the elements that are not the top level in q2.
After 3, the elements in q2 will be saved back to q1 to facilitate the next entry of other elements
//Two queue implementation stacks Queue<Integer> queue1=new LinkedList<>(); Queue<Integer> queue2=new LinkedList<>(); public void push(int node) {//There's nothing to say about the pressing element. It's the same as the stack operation. First, use a queue to store the pressed element queue1.offer(node); } public int pop(){ //When going out of the stack, we need to pay attention to the fact that the queue in q1, the queue in 123 and the stack out should be three, so we can go out of the queue one by one, and store the elements that are not top-level elements in q2, // After 3, the elements in q2 will be saved back to q1 to facilitate the next entry of other elements while (queue1.size()!=1){ queue2.offer(queue1.poll()); } int result=queue1.poll(); while(!queue2.isEmpty()){ queue1.offer(queue2.poll()); } return result; }
I'm not sure whether the code is wrong or the team. Let's check the problem one day.