思路:
我的评价是有手就行,就相当于链表的删除操作,进行遍历,遍历过程中找到目标值进行覆盖就行,注意一下这里我们采用哨兵位节点,也称为哑节点,开辟出来指向链表头节点,可以使对头节点的操作变简单很多,这个哨兵位节点的值可以不考虑,他只是用来攀搭头结点的舔狗(呜呜)。
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* dummyHead = malloc(sizeof(struct ListNode)); dummyHead->next = head; struct ListNode* curr = dummyHead;//定义哨兵位节点 while (curr->next) { if (curr->next->val == val) { curr->next = curr->next->next;//遍历到目标点进行覆盖 } else { curr = curr->next; } } head = dummyHead->next; free(dummyHead); //有借有还,记得归还哨兵位节点和申请的空间 return head; }
反转链表🤔
链接:反转链表
题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表
示例 :
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
思路:
1.创建一个新的中间节点我命名为 next ,将当前节点的下一个节点存放在next 节点中
2.链接 next 和当前节点,将 next 指向 当前节点实现反转,将原来指向下一节点的内容销毁掉(头部指向NIULL即可);
3.重复上述过程即可
以上是整体思路实现,而代码实现我们有两条路可以走,分别是迭代和递归,实现思路是一样的:
迭代:
struct ListNode* reverseList(struct ListNode* head){ struct ListNode* next = NULL; struct ListNode* prev = NULL; while(head) { next = head->next; head->next = prev; prev = head; head = next; } return prev; }
递归:
递归又分为了向前递归和向后递归,一般采用从前向后递归:
struct ListNode* reverse(struct ListNode* cur,struct ListNode* prev) { if(cur==NULL) { return prev; } struct ListNode* next = cur->next; cur->next = prev; return reverse(next,cur); //可以与双指针法对比,其实逻辑是一样的,只是用递归实现而已 } struct ListNode* reverseList(struct ListNode* head) { return reverse(head,NULL); }
从后向前递归:
struct ListNode* reverseList(struct ListNode* head) { if(!head || !head->next) return head; struct ListNode* cur = reverseList(head->next);//反转第二个节点后的所有节点 head->next->next = haed;//反转第二个节点与头节点 head->next = NULL;//头节点处理 return cur; }
链表的中间结点🤔
链接:链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点,如果有两个中间结点,则返回第二个中间结点。
奇数个返回中间节点:
思路:
方法一就是老老实实去遍历链表,算出链表长度,再找出中间节点位置,走过去返回他,属于暴力求解,笨且效率不高,这里就不做代码展示;
方法二巧用快慢指针,如下图:
我们定义两个指针,慢指针一次走一步,快指针一次走两步,不管链表节点数是奇是偶,慢指针最后必定落在中间节点;当链表节点为偶数个时,最后快指针将落在最后一个节点上,所以只需要判断快指针的 next 节点为不为空即可
struct ListNode* middleNode(struct ListNode* head){ struct ListNode* guard = malloc(sizeof(struct ListNode)); guard->next = head;//定义哨兵位节点 struct ListNode* fast = guard; struct ListNode* slow = guard; while(fast) { slow = slow->next;//慢指针一次走一步 if(fast->next) { fast = fast->next->next;//快指针一次走两步 } else { return slow; } } return slow; }