Daily brushing of LeetCode---Hand tearing single linked list exercises (1)

content

1. Remove the linked list element

2. Reverse the linked list

3. The intermediate node of the linked list

4. The kth node from the bottom in the linked list

5. Merge two ordered linked lists

6. Linked list segmentation


1. Remove the linked list element

  • Direct link:

remove list element

  • topic:

  •  Ideas:

This question needs to consider a variety of situations. The conventional situation is like Example 1, there are multiple nodes, and the val is not continuous, but what about the unconventional? What about when val is continuous? When the head is val? Therefore, it is necessary to classify and discuss

General situation:

Need to define two pointers prev and cur, cur points to the first data, prev points to the previous one of cur. Traverse whether the data pointed to by cur is val, if so, point the next node of prev to the next node of cur, cur=cur->next, prev follows cur until cur goes to NULL

Consecutive vals:

When we observe carefully, it is not difficult to find that continuous val can be solved under normal circumstances, but head val cannot.

Head val:

At this time, in addition to the two pointers prev and cur just defined, there is also a head pointing to the head. When the head is val, point cur to the next position, and head moves along with it until the data pointed to by cur is not val , assign head to prev. The rest can then be handled as usual.

  • code show as below:
struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode*cur=head;
    struct ListNode*prev=NULL;
    while(cur)
    {
        if(cur->val!=val)
        {
            prev=cur;
            cur=cur->next;
        }
        else
        {
            struct ListNode*next=cur->next;
            if(prev==NULL)
            {
                free(cur);
                cur=next;
                head=next;
            }
            else
            {
                prev->next=cur->next;
                free(cur);
                cur=prev->next;
            }
        }
    }
    return head;
}

2. Reverse the linked list

  • Direct link:
  • topic:

  • Ideas:

Method 1: Three pointers flip the direction

Three pointers n1, n2, and n3 are defined to point to NULL, the first data, and the second data, respectively. Let the next of n2 point to n1, assign n2 to n1, then assign n3 to n2, and then perform the operation of n3=n3->next, and then repeat the above operations until n2 points to empty. However, it should be noted that you must first determine whether the linked list is NULL, and if so, return NULL. In addition, you must also ensure that when n3 is empty, do not move, and directly assign n3 to n2.

  • code show as below:
struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode*n1=NULL;
    struct ListNode*n2=head;
    struct ListNode*n3=n2->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        {
            n3=n3->next;
        }
    }
    return n1;
}

Method 2: head plug

This method needs to create another linked list, create a new header newhead to point to NULL, and then define a pointer cur to point to the first data of the original linked list, pay attention to define a pointer next to point to the next node of cur. Traverse the original linked list, remove the node and insert it into the linked list where newhead is located. Each time the newhead is updated, it is assigned to cur, as shown in the figure:

  •  code show as below:
struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode*cur=head;
    struct ListNode*next=cur->next;
    struct ListNode*newhead=NULL;
    while(cur)
    {
        cur->next=newhead;
        newhead=cur;
        cur=next;
        if(next)
        {
            next=next->next;
        }
    }
    return newhead;
}

3. The intermediate node of the linked list

  • Direct link:

Intermediate node of linked list

  • topic:

  •  Ideas:

Fast and slow pointer

This question should pay attention to the odd and even numbers. If it is an odd number, such as example 1, then the value of the intermediate node is 3. Otherwise, if it is an even number, such as example 2, the second intermediate node is returned. In this question, we define two pointers slow and fast to point to the location of the first data. The difference is that slow takes 1 step at a time and fast takes 2 steps at a time. When fast goes to the tail pointer, slow is the intermediate node

  •  code show as below:
struct ListNode* middleNode(struct ListNode* head){
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

4. The kth node from the bottom in the linked list

  • Direct link:

The kth node from the bottom in the linked list

  • topic:

  •  Ideas:

Fast and slow pointer

Define two pointers slow and fast, let fast take k steps first, and then let slow and fast go at the same time. When fast goes to the end, slow is the kth last, because in this case, the gap between slow and fast is always k. It ends when fast goes to empty. This question can also take k-1 steps, but it ends when fast reaches the end, that is, when the next node of fast points to empty, it is the same. Take k steps as an example, as shown in the figure:

  •  code show as below:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode*fast=pListHead;
    struct ListNode*slow=pListHead;
    while(k--)
    {
        //if判断,防止k大于链表的长度
        if(fast==NULL)
            return NULL;
        fast=fast->next;
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

5. Merge two ordered linked lists

  • Direct link:

Merge two sorted linked lists

  • topic:

  •  Ideas:

Method 1: Merge (take the small tail) --- the leading node

Assuming that the head of the new linked list is called head and points to NULL, a pointer tail needs to be defined to facilitate subsequent tail finding, compare the values ​​of list1 and list2 nodes in turn, put the smaller ones on the head of the new linked list, update tail, and then put list1 Or update list2. When one of the two linked lists of list1 and list2 is empty, just copy all the remaining elements of the remaining linked lists into it.

  •  code show as below:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    //检查list1或list2一开始就为NULL的情况
    if(list1==NULL)
    {
        return list2;
    }
    if(list2==NULL)
    {
        return list1;
    }
    struct ListNode*head=NULL;
    struct ListNode*tail=head;
    while(list1&&list2)
    {
        if(list1->val<list2->val)
        {
            if(tail==NULL)
            {
                head=tail=list1;
            }
            else
            {
                tail->next=list1;
                tail=list1;
            }
            list1=list1->next;
        }
        else
        {
            if(tail==NULL)
            {
                head=tail=list2;
            }
            else
            {
                tail->next=list2;
                tail=list2;
            }
            list2=list2->next;
        }
    }
    //当list1和list2其中一个走到空的情况
    if(list1==NULL)
    {
        tail->next=list2;
    }
    else
    {
        tail->next=list1;
    }
    return head;
}

Method 2: The head node of the sentinel bit

Explain the leading node:

For example, the same linked list stores 1, 2, and 3. There are only these three nodes without the head node, and the head points to 1. The head node also stores 3 values, but there are 4 nodes, head points to the head node, this node does not store valid data

 The leading node has the following advantages. It is not necessary to judge whether the head and tail are empty, nor do you need to judge whether the list1 and list2 are empty, which will be very convenient. The same idea as the above, take the small down tail plug and link it directly to the back of the tail. But pay attention to returning the next of the head when returning, because the linked list given by the title does not take the lead, and the head itself points to that head, so the next one must be returned.

  • code show as below:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode* head = NULL, * tail = NULL;
    head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->next = NULL;
    while (list1 && list2)
    {
        if (list1->val < list2->val)
        {
            tail->next = list1;
            tail = list1;
            list1 = list1->next;
        }
        else
        {
            tail->next = list2;
            tail = list2;
            list2 = list2->next;
        }
    }
    //当list1和list2其中一个走到空的情况
    if (list1 == NULL)
    {
        tail->next = list2;
    }
    else
    {
        tail->next = list1;
    }
    struct ListNode* list = head->next;
    free(head);
    head = NULL
        return list;
}

6. Linked list segmentation

  • Direct link:

Linked list split

  • topic:

  •  Ideas:

Define two linked lists lesshead and greaterhead. Traverse the original linked list, insert < x into linked list 1, insert > x into linked list 2, and finally link linked list 1 and linked list 2. In defining two tail pointers to follow the new elements of linked lists 1 and 2

  •  code show as below:
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode* lessHead, * lessTail, * greaterHead, * greaterTail;
        lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));
        greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
        lessTail->next = greaterTail->next = NULL;
        struct ListNode* cur = pHead;
        while (cur)
        {
            if (cur->val < x)
            {
                lessTail->next = cur;
                lessTail = lessTail->next;
            }
            else
            {
                greaterTail->next = cur;
                greaterTail = greaterTail->next;
            }
            cur = cur->next;
        }
        //合并
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL;
        struct ListNode* list = lessHead->next;
        free(lessHead);
        free(greaterHead);
        return list;
    }
};

Guess you like

Origin blog.csdn.net/bit_zyx/article/details/123613662