Leetcode (leetcode) classic topic sharing phase 2 - linked list

Introduction of the second issue

The main topic of this blog is some classic OJ questions about linked lists, which are difficult. I hope you can read them patiently.

1. Reverse linked list

Title introduction:
Give you the head node head of the singly linked list, please reverse the linked list and return the reversed linked list.
OJ link
Analysis of ideas: define a new head, insert the elements of the original linked list to the back of the new head in turn, and finally return to the new head.
Time Complexity: O(N)
Diagram:
insert image description here
Code Implementation:

struct ListNode* reverseList(struct ListNode* head)
{
    
    
    struct ListNode* rehead=NULL;//新头
    struct ListNode* cur=head;
    while(cur)//遍历链表
    {
    
    
        struct ListNode* tmp=cur;
        cur=cur->next;
        //头插
        tmp->next=rehead;
        rehead=tmp;
    }
    return rehead;
}

2. Remove linked list elements

Topic introduction:
You are given a head node of a linked list headand an integer val, please delete all nodes in the linked list Node.val == valthat , and return a new head node.
OJ link
Analysis of ideas:
Method 1: Traverse the array, find the target element and delete it.
Time complexity: O(N^2)
This algorithm is simple in idea, but the efficiency is low, so we will not use it here.
Method 2: Declare a new header, traverse the original linked list, and end valthe elements of the original linked list into the new linked list.
Time complexity: O(N)
Diagram:
insert image description here

Code:

struct ListNode* removeElements(struct ListNode* head, int val)
{
    
    
	//声明新头和新尾
	struct ListNode* newhead = NULL, * newtail = NULL;
	//遍历原链表
	struct ListNode* cur = head;
	while (cur)
	{
    
    
		//如果原链表的元素不为val就尾插到新链表中
		if (cur->val != val)
		{
    
    
			struct ListNode* tmp = cur;
			cur = cur->next;
			//新链表为空的情况
			if (newhead == NULL)
			{
    
    
				tmp->next = NULL;
				newtail = newhead = tmp;
			}
			//一般情况
			else
			{
    
    
				tmp->next = NULL;
				newtail->next = tmp;
				newtail = newtail->next;
			}
		}
		else
		{
    
    
			cur = cur->next;
		}
	}
	return newhead;
}

3. Find the middle node of the linked list

Topic introduction:
Given a non-empty singly linked list whose head node is head, return the middle node of the linked list. If there are two intermediate nodes, return the second intermediate node.
OJ link
idea: fast and slow pointers. Define a pair of fast and slow pointers, where the slow pointer only takes one step at a time, and the fast pointer takes two steps at a time. When the fast pointer has traversed the linked list, the slow pointer stops in the middle of the linked list.
Note that it is necessary to classify and discuss whether the number of linked list nodes is even or odd .
Graphic:
Please add a picture description
Please add a picture description
code implementation:

struct ListNode* middleNode(struct ListNode* head)
{
    
    
    struct ListNode* slow,*fast;
    slow=fast=head;
    while(fast&&fast->next)
    {
    
    
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

4. Find the k-th last node in the linked list

Topic introduction: Input a linked list and output the k-th last node in the linked list.
OJ link
Analysis of ideas: fast and slow pointers. The fast pointer goes k steps first, and then the two pointers go together. When the fast pointer goes to empty, the slow pointer goes to the target node.
Illustration:
Please add a picture description

Code:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{
    
    
    struct ListNode* fast=pListHead,*slow=pListHead;
    //如果链表为空 直接返回NULL
    if(pListHead==NULL)
    {
    
    
        return NULL;
    }
    //快指针先走k步
    while(k)
    {
    
    
        //如果快指针已经为空了,但是k还不为0,说明k比链表总长度都大,直接返回NULL
        if(fast==NULL)
        {
    
    
            return NULL;
        }
        fast=fast->next;
        k--;
    }
    while(fast)
    {
    
    
        slow=slow->next;
        fast=fast->next;
    }
    return slow;
}

5. Merge two sorted lists

Title introduction: Merge two ascending linked lists into a new ascending linked list and return. The new linked list is formed by splicing all the nodes of the given two linked lists.
Analysis of OJ link
ideas: Create a new head, compare the elements of the two linked lists in turn, each time insert the tail of the smaller (or equal) element in the linked list to the new head, and stop the comparison when a linked list is empty. Then link the linked list that is not empty to the new linked list.
Graphic:
Please add a picture description
code implementation:

  1. Without the front page of the table (more troublesome)
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    
    
    struct ListNode* newhead=NULL;
    struct ListNode* newtail=NULL;
    //判断特殊情况
    if(!list1)
    {
    
    
        return list2;
    }
    if(!list2)
    {
    
    
        return list1;
    }
    //只要有一个链表遍历完就退出循环
    while(list1&&list2)
    {
    
    
        if(list1->val<=list2->val)
        {
    
    
            struct ListNode* tmp=list1;
            list1=list1->next; 
            tmp->next=NULL;
            if(newhead==NULL)
            {
    
    
                newtail=newhead=newtail=tmp;
            }
            else
            {
    
    
                newtail->next=tmp;   
                newtail=newtail->next;
            }
        }
        else
        {
    
    
            struct ListNode* tmp=list2;
            list2=list2->next; 
            tmp->next=NULL;
            if(newhead==NULL)
            {
    
    
                newtail=newhead=newtail=tmp;
            }
            else
            {
    
    
                newtail->next=tmp;   
                newtail=newtail->next;
            }
        }
    }
    //循环结束后,将剩下的节点链接致新链表后面
    if(list1)
    {
    
    
        newtail->next=list1;
    }
    if(list2)
    {
    
    
        newtail->next=list2;
    }
    return newhead;
}
  1. Front page with watch
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    
    
    //申请表头
    struct ListNode* newhead=(struct ListNode*)malloc(sizeof(struct ListNode));
    newhead->next=NULL;
    struct ListNode* cur=newhead;
    while(list1&&list2)
    {
    
    
        if(list1->val<=list2->val)
        {
    
    
            cur->next=list1;
            list1=list1->next;
        }
        else
        {
    
    
            cur->next=list2;
            list2=list2->next;
        }
        cur=cur->next;
    }
    if(list1)
        cur->next=list1;
    if(list2)
        cur->next=list2;
    struct ListNode* tmp=newhead->next;
    free(newhead);
    return tmp;
}

Summarize

This blog mainly explains some basic and simple topics. Thank you for reading it patiently. The next issue will increase the difficulty. Come on, everybody!
insert image description here

Guess you like

Origin blog.csdn.net/m0_72482689/article/details/127825584