Eleven common interview questions in linked list [detailed explanation 12]

Interview questions in linked list

1, [Leetcode] 203 remove linked list elements

203 remove linked list elements

[Title Description]: give you a head node of the linked list and an integer val. please delete all nodes in the linked list that meet Node.val == val and return a new head node

This problem is the same as the removeAllKey method for deleting all nodes with key value in the single linked list.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
         //The removeElements function has given the head node head, so you don't need to add this
    if(head == null){
        return null ;
    }
    ListNode prev=head;
    ListNode cur=head.next;
    while(cur!=null){
        if(cur.val==val){
            prev.next=cur.next;
            cur=cur.next;
        }else{
            prev=cur;
            cur=cur.next;
        }
    }
    if(head.val==val){
        head=head.next;
    }
    return head;//Returns the new header node
    //The returned ListNode is essentially the header node after deleting all val, and returns the deleted header
       
    }
}

2, [Leetcode] 206 reverse linked list (reverse linked list)

206 reverse linked list

[Title Description]: give you the head node of the single linked list. Please reverse the linked list and return the reversed linked list.

The logic analysis is as follows:

First, we draw a single linked list and make logical analysis according to the single linked list.

To reverse a single linked list is to reverse a single linked list. Is the reverse linked list the reverse data? Please think

Is this the final result we want?

Obviously, it's not the result we want. Why?

Because it's crossed? Hehe, of course not. To solve this problem, we must be clear that reverse linked list is not reverse data, reverse is not reverse data, and the real requirement of reverse is that the node itself should also be reverse.

How did he reverse it? Maybe we can think about this by head inserting

Define a cur to represent the current node to be reversed, and then define a curNext to record its next node. Use curNext to record the next to modify the cur of the current node

==Question: = = why define newHead?

newHead is the latest head node, but in the whole process, newHead acts as the precursor of each node.

What does that mean?

Because the logic of the above inversion is similar to that of header interpolation, newHead can be regarded as the precursor prev of each node to make reasonable use of the nature of header interpolation.

The analysis is shown in the figure:

The complete code is as follows:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        // if(head==null) / / when the single linked list is empty
        // return null;// If the single linked list is empty, head can also be returned
        // if(head.next==null) / / the first node is empty
        // return head;
        if(head==null || head.next==null) return head;
        ListNode cur=head;
        ListNode newHead=null;
        while(cur!=null){//cur is not equal to null, indicating that the linked list has not been traversed
            ListNode curNext=cur.next;
            cur.next=newHead;
            newHead=cur;
            cur=curNext;
        }
        return newHead;
    }
}

3, [Leetcode] 876 intermediate node of linked list

876 intermediate node of linked list

[Title Description]: given a non empty single linked list whose head node is head, return the intermediate node of the linked list.

If there are two intermediate nodes, the second intermediate node is returned.

Requirement: only go through the linked list once to find the intermediate node

If we use the length method to solve this problem, we need to traverse the linked list twice to complete it. We require that we can find the intermediate node only by walking through the linked list once, so we can use another method (i.e. fast and slow node points).

Drawing analysis logic:

Summary: when the number of nodes is odd, fast takes two steps and slow takes one step. When fast goes to fast.next is null, slow goes to the intermediate node.

Summary: when the number of nodes is even, fast takes two steps and slow takes one step. When fast goes to fast and fast is null, slow goes to the intermediate node.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        if(head==null){//Judge whether the head node is null. If it is null, there will be no intermediate node, and the head is returned
            return head;
        }
          ListNode fast=head;
          ListNode slow=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;//fast takes two steps
            slow=slow.next;//slow step
        }
        return slow;
    }
}

4, [sword finger offer] the penultimate node in the lin k ed list

The penultimate node in the lin k ed list

[Title Description]: Enter a linked list , output the penultimate node in the lin k ed list.

len - the penultimate node to find = the number of steps to take. After walking, you will find the penultimate node in the linked list

len-k = number of steps to take, as shown in the figure:

This method also needs to traverse the linked list twice, which is not the best consideration.

We can also consider trying to traverse the list once to solve the problem.

Let the fast pointer (Reference) go one step first, then fast reference fast and slow reference slow, and then go at the same time. When fast goes to fast.nex is null, the node referred to by slow is the penultimate node.

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null){
            return null;
        }
        if(k<=0){//If k is illegal
            return null;
        }
        ListNode fast=head;
        ListNode slow=head;
        //Let fast go k-1 first
        while(k-1!=0){
            if(fast.next!=null){//If the number of nodes is less than k,k is illegal
                 fast=fast.next;
                 k--;
            }else{
                return null;
            }
        }
        //After k-1, fast and slow go together
        while(fast.next!=null){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }
}

5, [Leetcode] 21 merge two ordered linked lists

21 merge two ordered linked lists

[Title Description]: merge two ascending linked lists into a new ascending linked list and return. The new linked list is composed of all nodes of a given two linked lists.

Logical analysis:

  • Define a virtual node newHead. The initial value is null. It is always the head node of the new linked list;

  • As long as the two references of headA and headB are not empty, compare their data values respectively. Whoever is young will be concatenated behind the virtual node newHead. The newHead cannot move. Define a TMP at the newHead node, make tmp.next equal to the current concatenated node each time, and then make TMP equal to the next node of TMP (TMP points to the next node of TMP).

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode headA, ListNode headB) {
        //If one of the two linked lists is empty and the other is not empty, the non empty linked list is returned
        if(headA==null){
            return headB;
        }
        if(headB==null){
            return headA;
        }
        //If both linked lists are empty, null is returned
        if(headA==null && headB==null){
            return null;
        }
           ListNode newHead=new ListNode(-1);
           ListNode tmp=newHead;
        //If both linked lists are not empty, compare the val values of the two linked lists
        while(headA!=null && headB!=null){
            if(headA.val < headB.val){
                tmp.next=headA;
                headA=headA.next;//Head a, go back
            }else{
                tmp.next=headB;
                headB=headB.next;//head, go back
            }
            tmp=tmp.next;//After the change, tmp also walked back
        }
        if(headA==null){
            tmp.next= headB;
        }
        if(headB==null){
            tmp.next= headA;
        }
        return newHead.next;//newHead is a virtual head node, while the real node in the linked list does not take the lead
    }
}

6, [niuke.com - program interview dictionary] CM 11 linked list segmentation

CM 11 linked list segmentation
[Title Description]: there is a header pointer ListNode* pHead of a linked list. Given a certain value of X, write a code to rank all nodes less than x before other nodes, and the original data order cannot be changed. Return the header pointer of the rearranged linked list.

Consider two questions first:

1. Judge how to deal with those larger than the fixed value and those smaller than the fixed value?

2. How to ensure that the data sequence remains unchanged after comparison?

Problem solving ideas:

  • Tail interpolation

  • Write a code less than the fixed value x in the original order, and then write a code greater than the fixed value x in the original order, and splice the codes at both ends.

  • Define the beginning less than x as bs (beginstart), the end less than x as be(beginend), the beginning greater than or equal to X as, and the end greater than or equal to X as ae. Finally, connect be and as.

    As shown in the figure:

The simple point is:

The logic analysis is shown in the figure below:

**Note: * * the next of the last node in the linked list is not null, which will lead to an endless loop of code, or the bs itself may be null

Example of linked list partition code:

import java.util.*;

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        // write code here
          ListNode cur=pHead;
            ListNode bs=null;
            ListNode be=null;
            ListNode as=null;
            ListNode ae=null;
            while(cur!=null){//It indicates that the linked list has not been traversed
                if(cur.val<x){
                    //Part I first insertion
                    if(bs==null){
                        bs=cur;
                        be=cur;
                    }else{
                        be.next=cur;
                        be=be.next;
                    }
                }else{
                    //Part II first insertion
                    if(as==null) {
                        as = cur;
                        ae = cur;
                    }else{
                        ae.next=cur;
                        ae=ae.next;
                    }
                }
                cur=cur.next;
            }
           if(bs==null){//Note that the first part is null, that is, there is no data less than x, then the next paragraph is returned
                return as;
            }
            //bs!=null
            be.next=as;//If the front of the first part is not null, the end of the first part and the beginning of the second part are spliced together
            if(as!=null){
                ae.next=null;
            }
            return bs;
        }
}

7, [sword finger offer] JZ56 deletes duplicate nodes in the linked list

JZ56 delete duplicate nodes in linked list
[Title Description]: there are duplicate nodes in a sorted linked list. Please delete the duplicate nodes in the linked list. The duplicate nodes are not retained and the chain header pointer is returned. For example, the linked list 1 - > 2 - > 3 - > 3 - > 4 - > 4 - > 5 is 1 - > 2 - > 5 after processing.

Logical analysis: because the nodes are already arranged in order, the same nodes must be arranged together.

1. Set a new virtual node (puppet node) newHead to identify the head node of the new node. cur is used to traverse the original linked list.

2. If cur.val=cur.next.val indicates that the first node is duplicate. If it is not equal to, it indicates that the first node is not duplicate. Put this node behind the newHead. Because the newHead cannot move, define another tmpH for it, so that the next of tmpH is equal to the current cur, and then let tmp=tmp.next go back and cur=cur.next go back.

Delete duplicate node codes in the linked list as follows:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
         ListNode newHead=new ListNode(-1);//Define a virtual node newHead
        ListNode tmp=newHead;
        ListNode cur=pHead;
        while(cur!=null){
            //cur.next!=null: judge whether there is only one node or tail node
            if(cur.next!=null && cur.val==cur.next.val){
                //In the process of cur, the remaining data may be the same, so cur.next needs to be added= Null this condition
                //Otherwise, a null pointer exception will occur
                while(cur.next!=null && cur.val==cur.next.val){
                    cur=cur.next;
                }
                cur=cur.next;//If cur takes one more step, it can skip the previous repeated node.
            }else{
                tmp.next=cur;
                tmp=tmp.next;//String the nodes together and tmp move back
                cur=cur.next;//cur, go back
            }
        }
        tmp.next=null;//Set manually to prevent the last node from being repeated and avoid dead cycle
        return newHead.next;
    }
 }

8, [online programming of 2016 school enrollment real questions] palindrome structure of OR36 linked list

Palindrome structure of OR36 linked list (frequently asked questions with headline and byte jumping)

[Title Description]: for a linked list, please design an algorithm with time complexity of O(n) and additional space complexity of O(1) to judge whether it is palindrome structure.

Given the header pointer A of A linked list, please return A bool value to represent whether it is A palindrome structure. Ensure that the length of the linked list is less than or equal to 900.

Test example:

1->2->2->1
 return: true

Question 1: if you define two references cur1 and cur2, cur1 goes back from the beginning and cur2 goes forward from the end? Is this method feasible?

It's not feasible because it's a one-way linked list. We don't know what the previous node of cur2 is.

solve the problem:

First find the intermediate node of the linked list and reverse the linked list after the intermediate node.

Logical analysis:

1. How to find the middle node of the linked list?

  • Define a fast and slow. Let fast take two steps at a time and slow take one step at a time. When fast.next is null, slow is the intermediate node of the linked list.

2. After the intermediate node is found, how to reverse it?

  • The intermediate node slow is equivalent to the precursor of the latter node. The latter node is defined as cur, and the node pointed to by fast is defined as curNext. It is used to record the value of cur.next, so that the value of cur.next is equal to the value of slow. Slow points to cur,cur=curNext,cur is not equal to null, and curNext moves backward, that is, curNext=cur.next;

3. After reversing, judge one by one. Head moves back and slow moves forward until they meet. The principle of judgment is that if the data values of head and slow are different, it will directly return to false.

The drawing analysis is as follows:

Palindrome structure code is as follows:

import java.util.*;

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
   if(A==null){
            return true;
        }
        if(A.next==null){
            //There is only one node, and one node is also a palindrome node
            return true;
        }
     //1. Find intermediate nodes
     ListNode slow = A;
     ListNode fast = A;
     while (fast != null && fast.next != null) {//Divided into odd and even cases
         fast = fast.next.next;
         slow = slow.next;
     }
     //The node pointed to by slow is the intermediate node of the linked list.
     //2. Flip
     ListNode cur = slow.next;
     while (cur != null) {//Only cur is not equal to null, can we continue to go down
         ListNode curNext = cur.next;
         cur.next = slow;
         slow = cur;
         cur = curNext;
     }
     ///After reversing, slow points to the last node
     //3. Judge the palindrome to see if the results of slow and head meet are equal
     while (slow != A) {
         if (slow.val != A.val) {
             return false;
         }
         if(A.next==slow){//If the linked list has even nodes (I don't understand. 1:29:00)
             return true;
         }
         A = A.next;
         slow = slow.next;
     }
     return true;
 }
}

9, [Leetcode] 141. Circular linked list

141. Circular linked list
[Title Description]: given a linked list, judge whether there are links in the linked list. Returns true if there are links in the linked list. Otherwise, false is returned.

If there is a node in the linked list that can be reached again by continuously tracking the next pointer, there is a ring in the linked list. In order to represent the rings in a given list, we use the integer pos to represent the position where the tail of the list is connected to the list (the index starts from 0). If pos is - 1, there is no ring in the linked list. Note: pos is not passed as a parameter, but only to identify the actual situation of the linked list.

What is a ring?

In human words, if the last node of the linked list is equal to a node in front of it, it means that there is a ring. If there is a ring in the linked list, return true.  Otherwise, return false . 

**Logical analysis: * * define a fast and then a slow. Fast takes two steps and slow takes one step. After each slow, see whether fast and slow meet. If they meet, it indicates that the linked list has rings. As shown in the figure:

Question 1: can fast take two steps at a time, three or four steps at a time?

No, because you may not meet, or you may meet after a long time.

Question 2: why can we meet two steps at a time?

Because fast takes two steps and slow takes one step, the difference between them is the smallest. Fast is always one step faster than slow, and it is also faster to catch up. If fast takes three or four steps, it may take a long time to catch up.

The ring list I code is as follows:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
         ListNode fast=head;
        ListNode slow=head;
        while(fast!=null && fast.next!=null){//There are even or odd numbers fast= Null is used to judge even nodes, fast. Next= null
            //Used to judge odd nodes
            //If none is null
            fast=fast.next.next;
            slow=slow.next;
            //Every time you walk, you have to see if fast and slow meet
            if(slow==fast){//Return true if encounter
                return true;
            }
        }
        return false;//false is returned whenever any of them is null
 }    
}

10, [Leetcode] 142. Circular linked list II (find the entry point of the linked list ring)

142. Ring linked list II (find the entry point of the linked list ring)

[Title Description]: given a linked list, return to the first node of the linked list. If the linked list is acyclic, null is returned.

In order to represent the rings in a given list, we use the integer pos to represent the position where the tail of the list is connected to the list (the index starts from 0). If pos is - 1, there is no ring in the linked list. Note that pos is only used to identify the ring and is not passed to the function as an argument.

Note: it is not allowed to modify the given linked list.

Set the distance from the start to the entry point as X, the distance from the entry point to the meeting point as Y, and the length of the ring as C

Under normal circumstances (walking around):

The slow distance is X+C-Y, and the fast distance is X+C+C-Y

The fast speed is twice the slow speed, which means that the fast distance is twice the slow distance.

That is, 2 (X+C-Y) = X+C+C-Y

Under special circumstances (in case of multiple turns):

The slow distance is X+C-Y, and the fast distance is X+NC+C-Y

The fast speed is twice the slow speed, which means that the fast distance is twice the slow distance.

That is, 2 (X+C-Y) = X+NC+C-Y

Drawing analysis:

Ring linked list II code example:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
          ListNode fast=head;
        ListNode slow=head;
        while(fast!=null && fast.next!=null){//There are even or odd numbers fast= Null is used to judge even nodes, fast. Next= null
            //Used to judge odd nodes
            //If none is null
            fast=fast.next.next;
            slow=slow.next;
            //It depends on whether fast and slow are finished every time
            if(slow==fast){//Return true if encounter
                break;
            }
        }
        if(fast==null || fast.next==null){//If it is empty, it means there is no ring, and if there is no bad, it returns null
            return null;
        }
        //If the loop execution ends, it indicates that there is a ring. If there is a ring, slow and fast meet
        slow=head; //Move the reference slow to the front
        while(fast!=slow){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }
}

11, [Leetcode] 160 intersecting linked list

160 intersecting linked list
[Title Description]: here are the head nodes headA and headB of the two single linked lists. Please find and return the starting node where the two single linked lists intersect. If two linked lists have no intersection, null is returned.

Question: what kind of situation is the intersection of two single linked lists?

It's a Y shape, similar to this

Example 1:

Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Intersected at '8'
Explanation: the value of intersection node is 8 (note that if two linked lists intersect, it cannot be 0).
Starting from their respective headers, linked list A is [4,1,8,4,5], and linked list B is [5,0,1,8,4,5].
In A, there are 2 nodes before the intersection node; In B, there are 3 nodes before the intersection node.

There are three ideas:

1. Find the length of two single linked lists

2. Calculate the difference between the lengths of two single linked lists

3. Let the long single linked list go first

==Question: = = there may be two single linked lists with different lengths. How do you know which is longer and which is shorter?

Define a single linked list with pl pointing to length

Define a single linked list with ps pointing to short

Assume default first

pl=headA

ps=headB

Then define a lenA, lenB, len = lenA lenB

len=lenA-lenB

If Lena lenb < 0, change the original default value, that is, pl=headB,ps=headA. After changing, let len = lenb Lena;

If Lena lenb > 0, it doesn't matter. It means that the original default is correct, and the len value must be a positive number.

The code under IDEA is written as follows:

public class TestMyLinkedList {
    //Code for intersecting two separate single linked lists
    public static void createCut(ListNode headA,ListNode headB){
        headA.next=headB.next.next;
    }
    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //1. Find the length and take the step of difference
        int lenA=0;
        int lenB=0;
        ListNode pl=headA;
        ListNode ps=headB;
        //Find length
        while(pl!=null){
            lenA++;
            pl=pl.next;
        }
        while (ps!=null){
            lenB++;
            ps=ps.next;
        }
        int len=lenA-lenB;
        if(len<0){
            pl=headB;
            ps=headA;
            len=lenB-lenA;
        }
        //pl must point to the longest single linked list
        for(int i=0;i<len;i++){
            pl=pl.next;
        }
        //2. ps and pl must be on the same starting line
        while(ps!=pl && pl!=null && ps!=null){
            ps=ps.next;
            pl=pl.next;
        }
        if(pl==ps && pl!=null){//The code here indicates that pl and ps have met
            return pl;
        }
        return null;
    }
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();//Get a single linked list object first
        myLinkedList.addLast(10);
        myLinkedList.addLast(16);
        myLinkedList.addLast(23);
        myLinkedList.addLast(46);
        myLinkedList.addLast(37);
        myLinkedList.addLast(12);
        myLinkedList.addLast(19);
        myLinkedList.display();

        MyLinkedList myLinkedList1 = new MyLinkedList();//Get a single linked list object first
        myLinkedList1.addLast(1);
        myLinkedList1.addLast(3);
        myLinkedList1.addLast(5);
        myLinkedList1.addLast(7);
        myLinkedList1.addLast(9);
        myLinkedList1.addLast(13);
        myLinkedList1.display();

        createCut(myLinkedList.head,myLinkedList1.head);//call
        ListNode   ret=getIntersectionNode(myLinkedList.head,myLinkedList1.head);
        System.out.println(ret.data);

The Leetcode code is written as follows:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //1. Find the length and take the step of difference
        int lenA=0;
        int lenB=0;
        ListNode pl=headA;
        ListNode ps=headB;
        //Find length
        while(pl!=null){
            lenA++;
            pl=pl.next;
        }
        while (ps!=null){
            lenB++;
            ps=ps.next;
        }
         pl=headA;
         ps=headB;
        int len=lenA-lenB;
        if(len<0){
            pl=headB;
            ps=headA;
            len=lenB-lenA;
        }
        //pl must point to the longest single linked list
        for(int i=0;i<len;i++){//Take the difference step
            pl=pl.next;
        }
        //2. ps and pl must be on the same starting line
        while(ps!=pl ){//    && pl!=null && ps!=null
            ps=ps.next;
            pl=pl.next;
        }
        if(pl!=null){//When the code comes here, it means that pl and ps meet. pl = = ps&& 
            return pl;
        }
        return null;    
    }
}

Tags: data structure Interview linked list

Posted on Sun, 21 Nov 2021 03:14:21 -0500 by onepixel