Once you learn it --- remove the same element in the linked list

Article directory

topic description

Given you a linked list head node head and an integer val, please delete all nodes satisfying Node.val == val in the linked list, and return a new head node.

Example:
insert image description here

Idea one:

To remove the node whose value is val in the linked list, we must traverse the linked list. The key is how we should operate during the traversal process. When we think about problems, we can first consider the more common situations, and then consider special situations.

1. Consider common situations
To remove a certain node, that is, let the previous node of the node point to the next node of the node to be removed, and then release the node to be removed. We can define 3 pointer variables: prev, cur, next.

prev: Record the previous node position of the node to be checked (previous).
cur: Record the node position currently being checked (current).
next: Record the next node (next) of the node to be checked.

insert image description here

When the node pointed to by the cur pointer is not the node to be removed, the three nodes move backward in turn.

insert image description here

When the cur pointer points to the node to be removed, we first let the node pointed to by the prev pointer point to next, then release the node pointed to by the cur pointer, assign the next pointer to the cur pointer, and then move the next pointer back.

insert image description here

Go on like this until the linked list is traversed, then the node with the value val will be deleted.

2. Considering the special situation
The analysis of common situations can only solve the general situation of the problem, but cannot solve the extreme situation of the problem. To really solve the problem, we need to take into account the corner cases of the problem. For example, when the node to be removed is the first node or the last node, when the linked list is empty.

1. When the first node of the linked list is the node to be removed
insert image description here

At this time, we need to point the head pointer to next first, then release the node pointed to by cur, and assign the next pointer to the cur pointer, and then move the next pointer back.

insert image description here

2. When the last node of the linked list is the node to be removed

When the last node is checked, cur points to the last node, and the next pointer points to the location pointed to by the node, which is NULL.

insert image description here

We analyze it with the method of the above conventional situation, and find that the idea of ​​the conventional situation is applicable to this special situation. And it is found that the termination condition of the traversal is that the traversal stops when cur is NULL.

insert image description here

3. When the incoming linked list is empty

We can find that if the incoming linked list is an empty linked list (NULL), the value of the cur pointer is empty at the beginning, and the termination condition of our traversal is to stop traversing when cur is NULL, so when the incoming linked list is empty, Execute directly to the end of the function, that is, return the head pointer (NULL).

Code example:

struct ListNode {
    
    
	int val;
	struct ListNode *next;
};

struct ListNode* removeElements(struct ListNode* head, int val)
{
    
    
	struct ListNode* prev = NULL;//记录待排查结点的前一个结点位置
	struct ListNode* cur = head;//记录当前正在排查的结点位置
	while (cur != NULL)//当cur为空时,循环停止
	{
    
    
		if (cur->val == val)//当前排查的结点是待移除的结点
		{
    
    
			struct ListNode* next = cur->next;//记录待排查结点的后一个结点位置
			if (cur == head)//待移除的结点是链表的第一个结点
			{
    
    
				head = next;//头指针指向next
				free(cur);//释放第一个结点
				cur = next;//将next指针赋值给cur指针
			}
			else//待移除的结点不是链表的第一个结点
			{
    
    
				prev->next = next;//prev指针指向的结点指向next
				free(cur);//将cur指针指向的结点释放掉
				cur = next;//将next指针赋值给cur指针
			}
		}
		else//当前排查的结点不是待移除的结点
		{
    
    
			prev = cur;//指针后移
			cur = cur->next;//指针后移
		}
	}
	return head;//返回新的头指针
}

Idea 2:

We may think that the code of idea 1 is more complicated. When we want to remove a certain node, we still need to judge whether the node is the first node. So is there any way to avoid this step?

The answer is yes. The way is to forcibly add a head node in front of the incoming linked list, and let the original head pointer of the linked list point to the head node, so that we don't need to judge whether the node to be removed is the first node (because Now the first node is the head node).

insert image description here

After adding the header node, we only need to write the code according to the logic of common situations. But there is one thing that cannot be forgotten, that is, after traversing the linked list, the position pointed to by the head node (that is, the position of the first node) must be assigned to the head pointer, and the head node must be released before returning to the head pointer.

insert image description here

Code example:

struct ListNode {
    
    
	int val;
	struct ListNode *next;
};
struct ListNode* removeElements(struct ListNode* head, int val)
{
    
    
	struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));//申请一个头结点,返回其地址
	guard->next = head;//让头结点指向链表的第一个结点
	struct ListNode* cur = guard->next;//cur指针指向原链表第一个结点
	struct ListNode* prev = guard;//prev指针指向头结点
	while (cur != NULL)//当cur为空时,循环停止
	{
    
    
		if (cur->val == val)//当前排查的结点是待移除的结点
		{
    
    
			struct ListNode* next = cur->next;//记录待排查结点的后一个结点位置
			prev->next = next;//prev指针指向的结点指向next
			free(cur);//将cur指针指向的结点释放掉
			cur = next;//将next指针赋值给cur指针
		}
		else//当前排查的结点不是待移除的结点
		{
    
    
			prev = cur;//指针后移
			cur = cur->next;//指针后移
		}
	}
	head = guard->next;//将头结点指向的位置赋值给头指针,使头指针指向链表第一个结点
	free(guard);//释放头结点
	guard = NULL;//及时置空
	return head;//返回新的头指针
}

おすすめ

転載: blog.csdn.net/weixin_62976968/article/details/131075764