Leek
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:
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 head
and an integer val
, please delete all nodes in the linked list Node.val == val
that , 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 val
the elements of the original linked list into the new linked list.
Time complexity: O(N)
Diagram:
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:
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:
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:
code implementation:
- 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;
}
- 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!