Data structure - singly linked list OJ question

Insert image description here


Preface

In the previous blog we learned what a singly linked list is and how to build a singly linked list!
Now let's test the learning results!

Tip: The topics in this blog are all from Niuke.com and Likou.com! I will include links to the two major websites in the question, so you can also practice!
If you have any link problems, you can provide timely feedback in the comment area!


1. Delete all nodes in the linked list that are equal to the given value val

Question link: OJ link
Insert image description here

Tip:
The number of nodes in the list is in the range [0, 104]
1 <= Node.val <= 50
0 <= val <= 50

Analysis of ideas:
Insert image description here

Code demo:

struct ListNode* removeElements(struct ListNode* head, int val) {
    
    
     struct ListNode* newhead = NULL;
     struct ListNode* move = head;
     struct ListNode* tail = NULL;

     while (move != NULL) {
    
    
         if (move->val != val) {
    
    
             if (tail == NULL) {
    
    //如果newnode为NULL,则tail等于newnode,则直接将结点地址赋予tail
                 newhead = tail = move;
                 move = move->next;
             }
             else {
    
    
                 tail->next = move;
                 move = move->next;
                 tail = tail->next;
             }
         }
         else {
    
    
             struct ListNode* temp = move;//新建结点保存要free的地址,以免free后造成节点丢失
             move = move->next;
             free(temp);
         }
     }
     if (tail)//如果新链表不为空,则将其尾结点的next置空
         tail->next = NULL;
     return newhead;
 }

2. Reverse a singly linked list

Question link: OJ link
Insert image description here
Insert image description here

Tip:
The range of the number of nodes in the linked list is [0, 5000]
-5000 <= Node.val <= 5000

Analysis of ideas:
Insert image description here

Code demo:

struct ListNode* reverseList(struct ListNode* head) {
    
    
    struct ListNode* move1 = head;
    struct ListNode* tail = head;
    if (head == NULL || head->next == NULL) {
    
    //如果链表为空或者只有一个结点,则不需要反转
        return tail;
    }
    struct ListNode* move2 = move1->next;
    while (move2) {
    
    
        struct ListNode* temp = move2->next;//保存下一个结点的地址,防止后面的节点丢失
        move2->next = move1;
        move1 = move2;
        move2 = temp;
    }
    tail->next = NULL;//尾结点的next置空
    struct ListNode* newhead = move1;//move1最后指向了反转链表的起始结点
    return newhead;
}

3. Return the intermediate node of the linked list

Question link: OJ link
Insert image description here

Tip:
The range of the number of nodes in the linked list is [1, 100]
1 <= Node.val <= 100

Analysis of ideas:
Insert image description here

Code demo:

struct ListNode* middleNode(struct ListNode* head){
    
    
    struct ListNode*move1=head;
    struct ListNode*move2=head;
    while(move2!=NULL&&move2->next!=NULL){
    
    //此处move2!=NULL和move2->next!=NULL
        move1=move1->next;                //的位置不能交换,否则会造成空指针错误
        move2=move2->next->next;
    }
    return move1;
}

4. Output the k-th node from the last in the linked list

Question link: OJ link
Insert image description here
idea analysis:
Insert image description here

Code demo:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    
    
    
    struct ListNode*move1=pListHead;
    struct ListNode*move2=pListHead;
    int i=k;
    while(i>0&&move2!=NULL){
    
    //move2向后移动k位
        move2=move2->next;
            i--;
    }
    if(move2==NULL&&i>0){
    
    //如果k大于链表结点数目,则返回NULL
        return move2;
    }
    while(move2){
    
    
        move1=move1->next;
        move2=move2->next;
    }
    return move1;
}

5. Merge two ordered linked lists

Question link: OJ link
Insert image description here
Insert image description here

Tip:
The range of the number of nodes in the two linked lists is [0, 50]
-100 <= Node.val <= 100. Both
l1 and l2 are arranged in non-decreasing order.

Analysis of ideas:
Insert image description here
Insert image description here
Insert image description here

Code demo:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    
    
    
    struct ListNode*move1=list1;
    struct ListNode*move2=list2;
    struct ListNode*newnode=NULL;
    struct ListNode*tail=NULL;
    while(move1!=NULL&&move2!=NULL){
    
    
        if(move1->val<=move2->val){
    
    
            if(tail==NULL){
    
    {
    
    //如果newnode为NULL,则tail等于newnode,则直接将结点地址赋予tail
            newnode=tail=move1;
            move1=move1->next;
            }
            else{
    
    
                tail->next=move1;
                move1=move1->next;
                tail=tail->next;
            }
        }
        else{
    
    
            if(tail==NULL){
    
    //如果newnode为NULL,则tail等于newnode,则直接将结点地址赋予tail
                newnode=tail=move2;
                move2=move2->next;
            }
            else{
    
    
                tail->next=move2;
                move2=move2->next;
                tail=tail->next;
            }
            }
    }
    if(move1==NULL){
    
    //如果链表1遍历完而链表2没有,则将链表2剩余结点尾插到newnode中
        while(move2!=NULL){
    
    
            if(tail==NULL){
    
    //如果newnode为NULL,则tail等于newnode,则直接将结点地址赋予tail
                newnode=tail=move2;
                move2=move2->next;
            }
            else{
    
    
                tail->next=move2;
                move2=move2->next;
                tail=tail->next;
            }
        }
    }
      if(move2==NULL){
    
    //如果链表2遍历完而链表1没有,则将链表1剩余结点尾插到newnode中
        while(move1!=NULL){
    
    
           if(tail==NULL){
    
    //如果newnode为NULL,则tail等于newnode,则直接将结点地址赋予tail
            newnode=tail=move1;
            move1=move1->next;
            }
            else{
    
    
                tail->next=move1;
                move1=move1->next;
                tail=tail->next;
            }
        }
    }
      return newnode;
}

6. Palindrome structure of linked list

Question link: OJ link

Insert image description here
Analysis of ideas:
Insert image description here
Insert image description here
Insert image description here

Code demo:

bool chkPalindrome(struct ListNode* A) {
    
    
    struct ListNode* move1 = A;
    struct ListNode* move2 = A;
    struct ListNode* move3 = A;
    struct ListNode* newnode = NULL;
    struct ListNode* tail = NULL;
    while (move2 != NULL&&move2->next != NULL ) {
    
    //找到中间节点
        move1 = move1->next;
        move2 = move2->next->next;
    }
    if (move2 == NULL);//如果节点个数为奇数,则move1向后移动一位
    else {
    
    
        move1 = move1->next;
    }
    while (move1 != NULL) {
    
    //将后半段链表头插到newnode中
        if (newnode == NULL) {
    
    
            newnode = tail = move1;
            move1 = move1->next;
            tail->next = NULL;
        }
        else {
    
    
            struct ListNode* temp = move1->next;
            move1->next = newnode;
            newnode = move1;
            move1 = temp;
        }
    }
    struct ListNode* cmp = newnode;
    while (move3 != NULL && cmp != NULL) {
    
    //比较原链表前半段和newnode是否相同
        if (move3->val != cmp->val) {
    
    
            return 0;
        }
        else {
    
    
            move3 = move3->next;
            cmp = cmp->next;
        }
    }
    return 1;
}

7. Split the linked list into two parts

Question link: OJ link
Insert image description here
idea analysis:
Insert image description here
Insert image description here

Insert image description here

Code demo:

ListNode* partition(ListNode* pHead, int x) {
    
    
        struct ListNode*head1=(struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode*head2=(struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode*tail1=head1;
        struct ListNode*tail2=head2;
        struct ListNode*move=pHead;
        while(move){
    
    
            if(move->val<x){
    
    
                tail1->next=move;
                move=move->next;
                tail1=tail1->next;
            }
            else{
    
    
                tail2->next=move;
                move=move->next;
                tail2=tail2->next;
            }
            }
        tail2->next=NULL;//将尾指针的next置空
        tail1->next=head2->next;
        struct ListNode*temp1=head1;
        struct ListNode*temp2=head2;
        head1=head1->next;//指针指向头结点的下一节点
        free(temp1);//释放掉创建的头结点
        free(temp2);
        return head1;
    }

8. Find the first public node

Question link: OJ link
Insert image description here
Insert image description here
Insert image description here
Insert image description here

Note:
After the function returns the result, the linked list must maintain its original structure.

Analysis of ideas:
Insert image description here
Insert image description here

Code demo:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    
    
    struct ListNode *move1=headA;
    struct ListNode *move2=headB;
    int len1=1,len2=1;
    while(move1){
    
    //得到链表A的长度
        move1=move1->next;
        len1++;
    }
    while(move2){
    
    //得到链表B的长度
        move2=move2->next;
        len2++;
    }
    int k=abs(len1-len2);//取相减的绝对值
    struct ListNode *moveA=headA;
    struct ListNode *moveB=headB;
    if(len1>len2){
    
    //较长的链表走k步
        while(k--){
    
    
            moveA=moveA->next;
        }
    }
      if(len1<len2){
    
    
        while(k--){
    
    
            moveB=moveB->next;
        }
    }
      while(moveA&&moveB){
    
    
        if(moveA==moveB)
            return moveA;//若地址相同则返回
        moveA=moveA->next;
        moveB=moveB->next;
    }
    return NULL;

9. Determine whether there is a cycle in the linked list

Question link: OJ link
Insert image description here
Insert image description here

hint:

The range of the number of nodes in the linked list is [0, 104]
-105 <= Node.val <= 105
pos is -1 or a valid index in the linked list.

Analysis of ideas:
Insert image description here

Code demo:

bool hasCycle(struct ListNode *head) {
    
    
    struct ListNode*move1=head;
    struct ListNode*move2=head;
    while(move1&&move2&&move2->next){
    
    //此处move2和move2->next的顺序不可交换
        move1=move1->next;           //否则会导致空指针错误
        move2=move2->next->next;
        if(move1==move2)
            return true;
    }
    return false;
}

Summarize

These nine singly linked list OJ questions are all very classic question types that I have ever seen!
Share it with everyone here!
I hope more people can better master the knowledge related to singly linked lists through these questions!

Guess you like

Origin blog.csdn.net/mdjsmg/article/details/132046363