Classic Linked List Problem: Key Challenges in Parsing Linked Lists

common child node

For example, this question: Given two linked lists, find their first common node.
Insert image description here
Let’s take a look at the specific description of the question A question from Niuke :
Insert image description here
Here we have four solutions:

Take a set or a hash

The idea is like this, we first traverse one of the linked lists and put it into the Map, and then traverse the second linked list and compare it with the Map. The first one that is the same is the common node.

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
    
    
        Map<ListNode, Integer>  map = new HashMap<>();
        while (pHead1 != null) {
    
    
            map.put(pHead1, pHead1.val);
            pHead1 = pHead1.next;
        }
        while (pHead2 != null) {
    
    
            if (map.containsKey(pHead2)) {
    
    
                return pHead2;
            }
            pHead2 = pHead2.next;
        }
        return null;
    }

Adopt stack

In this method, we need two stacks to traverse the two linked lists and push them into the stack respectively, and then pop them up at the same time. The group that is the same and is the latest to be popped out of the stack is the common node.

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
    
    
        Stack<ListNode>  stack1 = new Stack<>();
        Stack<ListNode>  stack2 = new Stack<>();
        while (pHead1 != null) {
    
    
            stack1.push(pHead1);
            pHead1 = pHead1.next;
        }
        while (pHead2 != null) {
    
    
            stack2.push(pHead2);
            pHead2 = pHead2.next;
        }
        ListNode ret = null;
        while (stack1.size() > 0 && stack2.size() > 0) {
    
    
            if (stack1.peek() == stack2.peek()) {
    
    
                ret = stack1.pop();
                stack2.pop();
            } else {
    
    
                break;
            }

        }
        return ret;
    }

Concatenate two strings

Look at the following two linked lists:
A: 1-4-6-2-3-5
B: 2-3- 5
Let’s try to splice a
AB: 1-4-6-2-3-5-2-3-5
BA: 2-3-5-1-4-6-2-3-5
We will find that as long as there are public nodes in the linked list, then we will find the common nodes when we traverse AB and BA node.

 public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
    
    
        if (pHead1 == null || pHead2 == null) {
    
    
            return null;
        }
        ListNode p1 =  pHead1;
        ListNode p2 = pHead2;
        while (p1 != p2) {
    
    
            p1 = p1.next;
            p2 = p2.next;
            //防止陷入死循环
            if (p1 != p2) {
    
    
                if (p1 == null) {
    
    
                    p1 = pHead2;
                }
                if (p2 == null) {
    
    
                    p2 = pHead1;
                }
            }
        }
        return p1;
    }

difference and double pointers

Traverse the two linked lists and record the lengths of the two linked lists, then first traverse the absolute value of nodes in the longer linked list (len1-len2), and then the two linked lists move forward at the same time. When the nodes are the same, they are common nodes.

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
    
    
        if (pHead1 == null || pHead2 == null) {
    
    
            return null;
        }
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        int len1 = 0, len2 = 0;
        while (p1 != null) {
    
    
            p1 = p1.next;
            len1++;
        }
        while (p2 != null) {
    
    
            p2 = p2.next;
            len2++;
        }
        int sub = Math.abs(len1 - len2);
        ListNode current1 = pHead1;
        ListNode current2 = pHead2;
        if (len1 > len2) {
    
    
            int a = 0;
            while (a < sub) {
    
    
                current1 = current1.next;
                a++;
            }
        }
        if (len2 > len1) {
    
    
            int a = 0;
            while (a < sub) {
    
    
                current2 = current2.next;
                a++;
            }

        }
        while (current1 != current2) {
    
    
            current1 = current1.next;
            current2 = current2.next;
        }
        return current2;
    }

This code is a Java method used to find the first common node in two linked lists. The method is named FindFirstCommonNode and receives two parameters pHead1 and pHead2, which represent the head nodes of the two linked lists respectively.
First, determine whether the two linked lists are empty. If one is empty, return null.
Then, use two pointers p1 and p2 to traverse the two linked lists respectively and calculate their lengths len1 and len2.
Next, calculate the absolute value sub of the difference between the lengths of the two linked lists.
Then, create two new pointers current1 and current2, pointing to the head nodes of the two linked lists respectively. If the length of linked list 1 is greater than the length of linked list 2, move current1 backward by sub nodes; if the length of linked list 2 is greater than the length of linked list 1, move current2 backward by sub nodes.
Finally, traverse the two linked lists at the same time until the first identical node is found and return it.

rotating linked list

We have two ideas:

  • Reverse the first k parts and N-k parts respectively and connect them to solve the problem.
  • Use double pointers to find the position of the reciprocal K. The specific implementation is as follows:
  public ListNode rotateRight(ListNode head, int k) {
    
    
     if(head==null || k==0){
    
    
         return head;
     }
     ListNode fast = head;
     ListNode slow = head;
     ListNode temp = head;
     int len = 0;
     while (head!=null){
    
    
         head = head.next;
         len++;
     }
     if(k%len==0){
    
    
         return temp;
     }
     while (k%len>0){
    
    
         k--;
         fast = fast.next;
     }
     while (fast.next!=null){
    
    
         fast = fast.next;
         slow = slow.next;
     }
     ListNode res = slow.next;
     fast.next = temp;
     slow.next=null;
return res;
    }
  1. First, determine whether the linked list is empty or whether the number of rotation positions is 0. If any condition is met, return the original linked list head node directly.
  2. Initialize three pointers: fast, slow and temp, all pointing to the head node of the linked list. At the same time, define a variable len to record the length of the linked list.
  3. Traverse the linked list and calculate the length of the linked list.
  4. Determine whether the number of rotation positions k is divisible by the length of the linked list. If it is divisible, no rotation is needed and the head node of the original linked list is returned directly.
  5. If the number of rotation positions k is not divisible by the length of the linked list, you need to find the node position corresponding to the remainder of k modulo the length of the linked list. The fast pointer is first moved forward by k%len positions, and then the fast and slow pointers are moved forward at the same time until the fast pointer reaches the end of the linked list. At this time, the position of the slow pointer is the new head node that needs to be rotated.
  6. The next node of the new head node is used as the tail node of the new linked list, and the tail node of the original linked list is connected to the head of the new linked list to form a new linked list.
  7. Returns the new head node of the linked list.

Guess you like

Origin blog.csdn.net/st200112266/article/details/133975798