目录
博主代码(处理了第一次的情况,略微繁琐,)时O(n),空O(1)
又是一个遍历然后对链表操作的题,简简单单?
主要思路差别不大,还是循环遍历,即迭代法(递归也行,比较浪费空间 )
对于这种影响到头结点(第一个结点,这是无头单链表,不是带头的单链表),要注意对头结点(第一个结点)的操作和别的结点操作有所区别,放不进循环,这类题,就是要我们有效的处理“头结点”
博主代码(处理了第一次的情况,略微繁琐,)时O(n),空O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
//assert(head);
//还是那句话,基本上单链表说的头,不过是第一节结点,而不是带头单链表
//基本的题,操作空间不大,老老实实做就行
//迭代法:还是那句话,非头的链表要考虑第一结点(第一次的特殊情况扔不进循环)
//原来位置修改(只是思路不同,操作差不了太多)较为复杂也要写第一次(返回的指针指向的结点要经过判断)的情况判断
struct ListNode* pNew = NULL;
struct ListNode* ptmp = NULL;
struct ListNode* pReturn = NULL;
while(head && head->val == val){//筛选一个不是val值的结点
ptmp = head->next;
free(head);
head = ptmp;
}
if(head == NULL){
return pNew;
}
//第一次的特殊情况
pNew = pReturn = head;
head = head->next;
pNew->next =NULL;//及时置NULL是好习惯
while(head){
if(head->val == val){
ptmp = head->next;
free(head);
head = ptmp;
}
else{
pNew->next = head;
head = head->next;
pNew = pNew->next;
pNew->next = NULL;//及时置空
}
}
return pReturn;
}
官方题解:时O(n)空O(1):
不像话,不是好习惯,官方题解的新建一个结点的对"头结点",这第一次的特殊处理要比我们选择的直接判断了第一次特殊情况的处理要好,但是这代码有坏习惯,你不free而是靠服务器实现,以后自己写代码的时候不注意就会导致内存泄漏——占着茅坑不拉屎(内占内存不用)
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode* dummyHead = malloc(sizeof(struct ListNode));
dummyHead->next = head;
struct ListNode* temp = dummyHead;
while (temp->next != NULL) {
if (temp->next->val == val) {
temp->next = temp->next->next;
} else {
temp = temp->next;
}
}
return dummyHead->next;
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/remove-linked-list-elements/solutions/813358/yi-chu-lian-biao-yuan-su-by-leetcode-sol-654m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
博主标题所说的好习惯:
1.博主代码里的及时置NULL操作;
若是没有会错误访问已经销毁的空间等一系列问题,
博主就因为第一次操作后没及时置NULL而在这道题上浪费了不少时间
2.官方题解的不free坏习惯:
虽然有明确告知malloc的空间不需要我们free,但是这种习惯很危险! 超级危险!!
每日一表情包:
都看到这里了,不点点赞,点点关注么?博主这么好的人哪里找啊!