Queue + matrix + linked list problem
- Cat dog queue
- Rotation print matrix (rotation matrix)
- . zigzag printing matrix
- Finding numbers in a matrix with ordered rows and columns
- Print a common part with two ordered linked lists
- Determine whether a linked list is a palindrome mechanism
- Divide the unidirectional linked list into small on the left, equal in the middle and large on the right according to a certain value
- Copy a linked list with random pointer nodes
- A series of problems on the intersection of two single chain tables
(from the fourth section of Zuoshen algorithm primary class)
1. Dog and cat line
Title: to implement a dog and cat queue structure, the requirements are as follows: the user can call add method to put the instance of cat or dog class into the queue; the user can call pollAll method to pop up all the instances in the queue according to the order of entering the queue; the user can call pollDog method to pop up the instances of dog class in the queue according to the order of entering the queue ; the user can call pollCat method to pop up the instances of cat class in the queue according to the order of entering the queue; the user can call isEmpty method to check whether there are instances of dog or cat in the queue; the user can call isDogEmpty method to check whether there are instances of dog class in the queue; the user can call isCatEmpty method to check whether there are instances of cat class in the queue Example.
Solution idea: stamp a time stamp every time you enter
Code:
public static class DogCatQueue { private Queue<PetEnterQueue> dogQ; private Queue<PetEnterQueue> catQ; private long count;//time stamp public DogCatQueue() { this.dogQ = new LinkedList<PetEnterQueue>(); this.catQ = new LinkedList<PetEnterQueue>(); this.count = 0; } public void add(Pet pet) { if (pet.getPetType().equals("dog")) { this.dogQ.add(new PetEnterQueue(pet, this.count++)); } else if (pet.getPetType().equals("cat")) { this.catQ.add(new PetEnterQueue(pet, this.count++)); } else { throw new RuntimeException("err, not dog or cat"); } } public Pet pollAll() { if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) { if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) { return this.dogQ.poll().getPet(); } else { return this.catQ.poll().getPet(); } } else if (!this.dogQ.isEmpty()) { return this.dogQ.poll().getPet(); } else if (!this.catQ.isEmpty()) { return this.catQ.poll().getPet(); } else { throw new RuntimeException("err, queue is empty!"); } } public Dog pollDog() { if (!this.isDogQueueEmpty()) { return (Dog) this.dogQ.poll().getPet(); } else { throw new RuntimeException("Dog queue is empty!"); } } public Cat pollCat() { if (!this.isCatQueueEmpty()) { return (Cat) this.catQ.poll().getPet(); } else throw new RuntimeException("Cat queue is empty!"); } public boolean isEmpty() { return this.dogQ.isEmpty() && this.catQ.isEmpty(); } public boolean isDogQueueEmpty() { return this.dogQ.isEmpty(); } public boolean isCatQueueEmpty() { return this.catQ.isEmpty(); } }
2. Rotation print matrix, rotation matrix
1) [Topic] given an integer matrix, please print it by turning. For example: 1 23 4 5 6 7 8 9 11 12 13 14 16 the result of printing is: 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10
Need Macro Thinking: solve by circle
- Two control nodes
Control node 1 (0, 0) → 0 row 0 column
Control node 2 (matrix.length - 1, matrix[0].length - 1) → node location in the last row and last column
- Print outer ring
If it's a bar structure (a=c or b=d), print a row or a column directly.
Otherwise:
Start from control node 1, print a line (except for the last point, and go to the last point of the line)
Then start at the last point of the row and print a column (except for the last point, go to the last point of the row)
Then start at the last point of the column and print the row from the end to the end (except for the first point, go to the first point of the column)
Finally, starting from the first point of the line, print the column from the bottom up (except for a little accident, return to the control node 1 position)
The process is as shown in the figure:
Code:
public class Code_06_PrintMatrixSpiralOrder { public static void spiralOrderPrint(int[][] matrix) { int a = 0;//Control node (0, 0) int b = 0; int c = matrix.length - 1;//Last point of control node (matrix.length - 1, matrix[0].length - 1) int d = matrix[0].length - 1; while (a <= c && b <= d) { printEdge(matrix, a++, b++, c--, d--);//Print one outer circle at a time. After printing, the two control nodes go in until they miss } } public static void printEdge(int[][] m, int a, int b, int c, int d) { if (a == c) {//Rod like structure for (int i = b; i <= d; i++) { System.out.print(m[a][i] + " "); } } else if (b == d) {//Rod like structure for (int i = a; i <= c; i++) { System.out.print(m[i][b] + " "); } } else { int curC = b; int curR = a; while (curC != d) {//Printing to the last node of the same line stops System.out.print(m[a][curC] + " "); curC++; } while (curR != c) {//Printing to the last node in the same column stops System.out.print(m[curR][d] + " "); curR++; } while (curC != b) {//Printing to the first node of the same line stops System.out.print(m[c][curC] + " "); curC--; } while (curR != a) {//Print to the first node of the same column System.out.print(m[curR][b] + " "); curR--; } } } public static void main(String[] args) { int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; spiralOrderPrint(matrix); } }
2) Rotation matrix (rectangle cannot rotate)
Also use the idea of circle Division
Exchange four positions at a time, repeat matrix.length - 1 time.
public class Code_05_RotateMatrix { public static void rotate(int[][] matrix) { int tR = 0; int tC = 0; int dR = matrix.length - 1; int dC = matrix[0].length - 1; while (tR < dR) { rotateEdge(matrix, tR++, tC++, dR--, dC--); } } public static void rotateEdge(int[][] m, int a, int b, int c, int d) { int times = d - b; int tmp = 0; for (int i = 0; i != times; i++) {//Buckle the boundary to change the position tmp = m[a][b + i];//Save the first point to the tmp variable m[a][b + i] = m[c - i][b];//Change the position of the fourth point to the position of the first point m[c - i][b] = m[c][d - i];//Change the third position to the last point position m[c][d - i] = m[a + i][d];//Change the position of the second point to the position of the third point m[a + i][d] = tmp;//Change the position of tmp variable to the second point } } public static void printMatrix(int[][] matrix) { for (int i = 0; i != matrix.length; i++) { for (int j = 0; j != matrix[0].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); } } public static void main(String[] args) { int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; printMatrix(matrix); rotate(matrix); System.out.println("========="); printMatrix(matrix); } }
3. Reverse one-way list and two-way list
4. Zigzag printing matrix
[Topic] given a matrix, print the matrix in zigzag way. For example, the result of zigzag printing is 1, 2, 5, 9, 6, 3, 4, 7, 10, 11, 8, 12.
Problem solving process:
- Two variables A and B are used to control the head and tail points of each printing
- A go right first, get to the last column, and then go down
- B go down to the last line and start to the right
- Know that A reaches the last point (position 18), or B reaches the end of the last point (position 18).
Code:
public class Code_08_ZigZagPrintMatrix { public static void printMatrixZigZag(int[][] matrix) { int a = 0; int b = 0; int c = 0; int d = 0; int endR = matrix.length - 1; int endC = matrix[0].length - 1; boolean fromUp = false;//Print from top left or bottom right while (a != endR + 1) {//a go to the last line, stop printLevel(matrix, a, b, c, d, fromUp);//Printing a = b == endC ? a + 1 : a;//The number of column A reaches the last column, and then goes down b = b == endC ? b : b + 1; d = c == endR ? d + 1 : d;//B line number comes to the last line, then go right c = c == endR ? c : c + 1; fromUp = !fromUp;//Each time we take back } System.out.println(); } public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) {//Printing if (f) { while (tR != dR + 1) { System.out.print(m[tR++][tC--] + " "); } } else { while (dR != tR - 1) { System.out.print(m[dR--][dC++] + " "); } } } public static void main(String[] args) { int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; printMatrixZigZag(matrix); } }
5. Find the number in the ordered matrix
[Topic] given an integer matrix with N*M and an integer k, each row and column of the matrix are ordered. Implement a function to determine whether K is in matrix. For example: 0 1 2 5 2 3 4 7 4 4 8 5 7 9 If K is 7, return true; if K is 6, return false.
[requirements] the time complexity is O(N+M), and the extra space complexity is O(1).
(upper right corner method, lower left corner method)
- A number goes left when it is smaller than the current value of the array, and goes down when it is larger than the current value.
- If you find it, there will be. If you don't find the array boundary, there will be none.
The process is as shown in the figure:
Code:
public class Code_09_FindNumInSortedMatrix { public static boolean isContains(int[][] matrix, int K) { int row = 0; int col = matrix[0].length - 1; while (row < matrix.length && col > -1) { if (matrix[row][col] == K) { return true; } else if (matrix[row][col] > K) { col--; } else { row++; } } return false; } public static void main(String[] args) { int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0 { 10, 12, 13, 15, 16, 17, 18 },// 1 { 23, 24, 25, 26, 27, 28, 29 },// 2 { 44, 45, 46, 47, 48, 49, 50 },// 3 { 65, 66, 67, 68, 69, 70, 71 },// 4 { 96, 97, 98, 99, 100, 111, 122 },// 5 { 166, 176, 186, 187, 190, 195, 200 },// 6 { 233, 243, 321, 341, 356, 370, 380 } // 7 }; int K = 233; System.out.println(isContains(matrix, K)); } }
6. Judge whether a linked list is palindrome structure
[Topic] given the header node head of a linked list, please judge whether the linked list is palindrome structure. For example: 1 - > 2 - > 1, return true. 1 - > 2 - > 2 - > 1, return true. 15 - > 6 - > 15, return true. 1 - > 2 - > 3, return false. Advanced: if the chain length is N, the time complexity reaches O(N), and the extra space complexity reaches O(1).
Written test: use auxiliary space to pass quickly
- Save the linked list with a stack, and then compare (method 1)
public static boolean isPalindrome1(Node head) { Stack<Node> stack = new Stack<Node>(); Node cur = head; while (cur != null) { stack.push(cur); cur = cur.next; } while (head != null) { if (head.value != stack.pop().value) { return false; } head = head.next; } return true; }
- Use the speed pointer to go to the intermediate node, and then load the later part into the stack, compare the front part of the stack and the chain list (method 2)
public static boolean isPalindrome2(Node head) { if (head == null || head.next == null) { return true; } Node right = head.next; Node cur = head; while (cur.next != null && cur.next.next != null) { right = right.next;//Fast and slow pointer to find the midpoint cur = cur.next.next; } Stack<Node> stack = new Stack<Node>(); while (right != null) { stack.push(right); right = right.next; } while (!stack.isEmpty()) { if (head.value != stack.pop().value) { return false; } head = head.next; } return true; }
Interview (with several variables):
Method 1: no auxiliary space
- First, the fast and slow pointer finds the intermediate node
- Reverse the following parts
- Start from the beginning and the end respectively to judge whether they are equal
- Whether it is palindrome or not, finally recover the data (reverse part and then reverse)
public static boolean isPalindrome3(Node head) { if (head == null || head.next == null) { return true; } Node n1 = head; Node n2 = head; 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; }
7. Divide the unidirectional linked list into small on the left, equal in the middle and large on the right according to a certain value
[Topic] given the head node of a one-way linked list, the value type of the node is integer, and then given an integer pivot. Realize a function to adjust the linked list. The left part of the linked list is the node whose value is less than pivot, the middle part is the node whose value is equal to pivot, and the right part is the node whose value is greater than pivot. In addition to this requirement, there are no more requirements for the adjusted node order. For example: List 9 - > 0 - > 4 - > 5 - > 1, pivot=3. After adjustment, the chain list can be 1 - > 0 - > 4 - > 9 - > 5, or 0 - > 1 - > 9 - > 5 - > 4. In a word, the left part is less than 3 nodes, the middle part is equal to 3 nodes (this part is empty in this case), and the right part is more than 3 nodes. There is no requirement for the node order within a certain part. (Dutch flag)
Advanced problem: add the following two requirements to the original problem. The sequence requirements are also made in the left, middle and right parts. The order of nodes in each part from left to right is the same as that in the original linked list. For example: List 9 - > 0 - > 4 - > 5 - > 1, pivot=3. The adjusted list is 0 - > 1 - > 9 - > 4 - > 5. While meeting the requirements of the original problem, the left nodes are 0 and 1 from left to right. In the original list, 0 appears first, followed by 1. In this case, the middle part is empty and will not be discussed. In the right part, the nodes are 9, 4 and 5 from left to right. In the original list, 9 appears first, then 4, and finally 5. If the chain length is N, the time complexity is O(N), and the extra space complexity is O(1).
Problem solving process:
- Prepare 6 node variables
- Put the nodes less than, equal to, and greater than at the link points of less, eq, and more in order until the end of traversing the linked list.
- Start from less and string the nodes in order to form the required list
As shown in the figure:
Code:
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) { sT.next = eH; eT = eT == null ? sT : eT; } // all reconnect if (eT != null) { eT.next = bH; } return sH != null ? sH : eH != null ? eH : bH; }
8. Copy the linked list with random pointer nodes
[title] a special link list Node class is described as follows: public class Node {public int value; public Node next; public Node rand; public Node (int data) {this. Value = data;}} value in Node class is Node value, next pointer is the same as the next pointer in normal single chain table, which points to the next Node, and rand pointer is the new pointer in Node class. This The pointer may point to any Node in the list, or it may point to null. Given the head Node of an acyclic single chain table composed of Node node type, please implement a function to complete the replication of all structures in the chain table, and return the head Node of the new chain table. Advanced: no additional data structure is used, only a limited number of variables are used, and the function to be realized in the original problem is completed within the time complexity of O(N).
Method 1: use hash table
- Take the original linked list p1 as the key and put it into hashmap
- Copy each node of p1 and place it as the value of hashmap.
- key is the original linked list node and value is the copy node.
- You can find the corresponding relationship through hashmap lookup. For example, if the next of the first node of p1 points to the key value of the second node, then the value of the first node in hashmap points to the value of the second node
Code:
public static Node copyListWithRand1(Node head) { HashMap<Node, Node> map = new HashMap<Node, Node>(); Node cur = head; while (cur != null) {//Put it in the key map.put(cur, new Node(cur.value)); cur = cur.next; } cur = head; while (cur != null) {//Map the correspondence to value map.get(cur).next = map.get(cur.next); map.get(cur).rand = map.get(cur.rand); cur = cur.next; } return map.get(head); }
Method two:
- First, traverse the linked list so that the first position of the original linked list node points to the copied node, the copied node points to the second position of the original linked list, and so on
- And rand can be found through the next relationship (for example, 1's rand points to 3, and now 3 points to 3 ', so 1's rand is equal to 3's next)
As shown in the figure:
Code:
public static Node copyListWithRand2(Node head) { if (head == null) { return null; } Node cur = head; Node next = null; // copy node and link to every node while (cur != null) {//copy node next = cur.next; cur.next = new Node(cur.value); cur.next.next = next; cur = next; } cur = head; Node curCopy = null; // set copy node rand while (cur != null) {//Copy rand relationship next = cur.next.next; curCopy = cur.next; curCopy.rand = cur.rand != null ? cur.rand.next : null; cur = next; } Node res = head.next; cur = head; // split while (cur != null) {//Copy node separated from the original linked list next = cur.next.next; curCopy = cur.next; cur.next = next; curCopy.next = next != null ? next.next : null; cur = next; } return res; }
9. A series of problems about the intersection of two single chain tables
[Topic] in this question, a single chain table may or may not have rings. Given the head nodes head1 and head2 of two single linked tables, the two linked tables may or may not intersect. Please implement a function. If two linked lists intersect, please return the first node intersected; if not, return null. Requirements: if the length of chain table 1 is N, the length of chain table 2 is M, the time complexity should reach O(N+M), and the extra space complexity should reach O(1).
The questions are divided into:
- 1) Judge whether the list has links or not?
- 2) The first node of two acyclic lists?
- 3) Do two linked lists intersect?
1) Judge whether the list has links or not?
Method 1: use hash table
- When traversing, put the node into the key, and then check whether the hash table has appeared?
- Find out that the first node put in is the first intersection node
Method 2: fast and slow pointer (fast pointer takes two steps at a time, slow pointer takes one step at a time)
- Prepare two pointers
- Fast pointer reaches null to prove acyclic
- When the fast and slow hands meet for the first time, the fast hands return to the starting point, from two steps at a time to one step at a time. When the fast and slow hands meet again, it must be the entrance of the ring.
2) The first intersection node of two acyclic lists?
Method 1: hashmap
- When traversing, put the node into the key, and then check whether the hash table has appeared?
- Find out that the first node put in is the first intersection node
Method 2: set out successively
- First, traverse the two linked lists respectively, and get the length len1, len2, end1, end2 (end is the last node)
- First, judge whether end1 and end2 are equal. If they are not, there is no intersection. Otherwise, they intersect
- If len1 is equal to len2, compare the length of len1 and len2. If the length of len1 and len2 is greatly reduced, then start (length difference) first, and then walk together. When the first is equal, it is the first node that intersects
public static Node noLoop(Node head1, Node head2) {//exannulate 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; } //Calculate the difference if (cur1 != cur2) { return null; } cur1 = n > 0 ? head1 : head2;//Locate long and short list 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; }
3) Do two linked lists intersect?
If loop1=loop2, it's topology 2. Loop1 walks through the loop to see if loop2 is found. If not, it's topology 1. If not, use hashmap to check whether the nodes of loop1 have appeared in loop2
Three topologies:
-
Two linked lists do not intersect
-
Two linked lists share one ring, and the ring has only one entry
-
Two linked lists share one ring, and the ring has two entrances
Code:
public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { Node cur1 = null; Node cur2 = null; if (loop1 == loop2) {//Topology 2 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; } }