1. Title Description:
Here are the tips given in the original question:
Here is the definition form of interface function and linked list given in the original question:
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeElements(struct ListNode* head, int val){ }
Let's start tearing the question by hand:
2. Ideas:
2.1 general framework
1. Define two pointers, one prev and one cur
2. Go through the linked list, and then find the node where the element I want to delete is located, that is, the value of cur is equal to the value to be deleted
3. Delete the cur node, ` ` prev - > next = cur - > next ', and then cur = cur - > next ` points to the next node.
2.2 preliminary realization
How to traverse
Exit the loop through the while loop and null cur, arrange a branch in the loop, delete it if it meets the requirements, and continue to traverse the next one if it does not meet the requirements
struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode*cur= head; struct ListNode*prev=NULL; while(cur) { if(cur->val=val) { prev->next=cur->next; free(cur); cur=prev->next; } else { prev=cur; cur=cur->next; } } }
However, it is found that the next is not clear. For simplicity, use three pointers
prev cur next
struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode*cur= head; struct ListNode*prev=NULL; while(cur) { if(cur->val=val) { struct ListNode*next=cur->next; prev->next=next; free(cur); cur=next; } else { prev=cur; cur=cur->next; } } }
This is more clear
2.3 special circumstances require classified discussion
- In this case, if the test sample is shown in the above figure, the original head node is not 1 but 2. The return value head needs to be processed here, and prev is NULL (to be solved)
Here is the solution: add a judgment statement to judge whether the element is equal to value
if(cur->val==val) { struct ListNode*next=cur->next; if(prev==NULL)//That is, cur at this point is the head { free(cur); head=next; cur=next; } else { prev->next=next; free(cur); cur=next; } }
- Continuous nodes need to be deleted (it can be solved originally)
- The last node needs to be deleted (it could have been solved)
- All 6 (can also be solved)
3. Overall realization
struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode*cur= head; struct ListNode*prev=NULL; while(cur) { if(cur->val==val) { struct ListNode*next=cur->next; if(prev==NULL)//That is, cur at this point is the head { free(cur); head=next; cur=next; } else { prev->next=next; free(cur); cur=next; } } else { prev=cur; cur=cur->next; } } return head; }
Summary:
The main element of this problem is still a classified discussion
4. Sentinel position head node method
Set up a sentinel head node to prevent classified discussion. This sentinel usually opens up a node to store the address of the head and turn the head into a non head node
struct ListNode* removeElements(struct ListNode* head, int val) { struct ListNode* guardHead = (struct ListNode*)malloc(sizeof(struct ListNode)); guardHead->next = head; struct ListNode* prev = guardHead; struct ListNode* cur = head; while (cur) { if (cur->val == val) { struct ListNode* next = cur->next; prev->next = next; free(cur); cur = next; } else { prev = cur; cur = cur->next; } } head = guardHead->next;//To prevent memory leakage, don't directly return sentinel. It's better to turn to head free(guardHead); return head; }
Summary:
There is no need for sentinel in this question, because it is not simpler. Of course, both methods are OK.
These are also two ideas for general problems of this type