Interview preparation ---------- linked list collection

Combine two ordered linked lists

Insert picture description here
Topic link!

Idea:
There are many solutions to this problem, which can be divided into two categories, one is recursive and the other is non-recursive. The specific implementation is not difficult, and you can see it clearly by looking at the code.

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    
    
        if(l1==NULL) return l2;
        if(l2==NULL) return l1;

        ListNode* phead = NULL;
        if(l1->val < l2->val){
    
    
            phead = l1;
            phead->next = mergeTwoLists(l1->next,l2);
        }else{
    
    
            phead = l2;
            phead->next = mergeTwoLists(l1,l2->next);
        }
        return phead;
    }
};



//非递归版本
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    
    
        ListNode* phead= new ListNode(-1,NULL);
        ListNode* op = phead;
        while(l1!=NULL && l2!=NULL){
    
    
            if(l1->val < l2->val){
    
    
                op->next = l1;
                l1=l1->next;
            }else{
    
    
                op->next = l2;
                l2=l2->next;
            }
            op = op->next;
        }

        if(l1!=NULL) op->next = l1;
        if(l2!=NULL) op->next = l2;

        op = phead->next;
        delete(phead);
        return op;
    }
};


Reverse linked list

Insert picture description here
Topic link!

Idea: This
question is very simple, just look at the code; or look at a picture I drew.
Insert picture description here

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* reverseList(ListNode* head) {
    
    
        if(head==NULL || head->next==NULL) return head;

        ListNode *t,*p,*q;
        t = NULL;
        p = q = head;
        while(q!=NULL){
    
    
            q=q->next;
            p->next = t;
            t = p;
            p = q;
        }
        return t;
    }
};

The kth node from the bottom of the linked list

Insert picture description here

Topic link!
Idea: This
question is a question of fast and slow pointers, or double pointers. Two variables, one fast and one slow, let the fast pointer go k steps first; then go at the same time, when the fast pointer reaches the end. .

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
    
    
        if(head==NULL || k==0) return NULL;

        ListNode *p,*q;
        p = q = head;
        for(int i=1;i<=k-1;++i){
    
    
            q = q->next;
        }

        while(q->next!=NULL){
    
    
            p=p->next;
            q = q->next;
        }
        return p;
    }
};

Loop detection

Insert picture description here
Insert picture description here

Topic link

Idea: This
question really should be studied hard, first throw out the solution steps:

  1. First judge whether it is a ring?
  2. Find the length x of the ring;
  3. Let the quick pointer go x steps first;
  4. Then the fast and slow pointers move at the same time, and the node they meet is the entry point of the ring.

(Note: This question also solves a special case, as in the second case in the figure above, exactly one linked list is a ring)

Everyone understands the reason for judging the ring. Only when the ring is formed can there be subsequent problem-solving steps; why is the length of the ring required? In fact, there is a question that can explain this reason, that is , the question of the kth node from the bottom. The length of the ring is to make the fast pointer go so many steps first, and it is also to make the fast pointer and the slow pointer meet faster . Because let the fast pointer go first, it can be simply understood as allowing the fast pointer to complete the loop, while the slow pointer does not need to walk the loop.

Likou official explanation

Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:

    ListNode* check_huan(ListNode* head){
    
    
        if(head==NULL) return NULL;
        ListNode* slow = head;
        ListNode* fast = slow->next;

        while( fast!=NULL){
    
    
            if(slow==fast) return slow;  //这里也能处理特殊情况,比如只有一个节点的环
            slow = slow->next;
            fast = fast->next;
            if(fast!=NULL) fast = fast->next;
        }
        return NULL;
    }


    ListNode *detectCycle(ListNode *head) {
    
    
        ListNode* st = check_huan(head);
        if(st==NULL) return NULL;
        

        ListNode* t = st;
        int num = 1;
        while(st->next!=t){
    
    
            st = st->next;
            ++num;
        }
        ListNode* fast = head;
        for(int i=0;i<num;++i){
    
    
            fast = fast->next;
        }

        while(fast!=head){
    
    
            fast = fast->next;
            head = head->next;
        }
        return fast;
    }
};

K flip listInsert picture description here

Topic link!

Idea: This
question does have something. First of all, we should be familiar with flipping the linked list, then it is much easier to handle; we first use a for loop to read the k-length sub-linked list (note that it may fail to read , The specific code), and then pass this sub-linked list into the function for processing, and then the value of the function returns the head and tail pointers after flipping the sub-linked list. At this time, splicing is enough, and the above steps are repeated until the traversal of the linked list is completed.

Code:

class Solution {
    
    
public:
    // 翻转一个子链表,并且返回新的头与尾
    pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {
    
    
        ListNode* prev = tail->next;
        ListNode* p = head;
        while (prev != tail) {
    
    
            ListNode* nex = p->next;
            p->next = prev;
            prev = p;
            p = nex;
        }
        return {
    
    tail, head};
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
    
    
        ListNode* hair = new ListNode(0);
        hair->next = head;
        ListNode* pre = hair;

        while (head) {
    
    
            ListNode* tail = pre;
            // 查看剩余部分长度是否大于等于 k
            for (int i = 0; i < k; ++i) {
    
    
                tail = tail->next;
                if (!tail) {
    
    
                    return hair->next;
                }
            }
            ListNode* nex = tail->next;
            
             pair<ListNode*, ListNode*> result = myReverse(head, tail);
             head = result.first;
             tail = result.second;
            //tie(head, tail) = myReverse(head, tail);
            
            pre->next = head;
            tail->next = nex;
            pre = tail;
            head = tail->next;
        }

        return hair->next;
    }
};

Guess you like

Origin blog.csdn.net/weixin_43743711/article/details/114239279