链表的删除&&常见的问题

一. 链表有无头结点的区别(单链表)


首先
  我们需要了解,删除节点p, 我们只需要找到 p的上一个结点pre的位置, 进行 pre.next = p.next 即可。


 头结点: 指针域指向首元结点(具有实际意义的第一个元素结点) ,数据域可以不存任何信息,指针域指向单链表第一个元素的结点。头结点可有可无,但为了操作方便,一般情况下单链表都具有头结点
优点:
 为了减少程序的复杂性(添加和删除操作,在首元结点上有区别与其他的操作 ), 如果链表没有头结点,则删除或添加时都得需要判断一次首元结点,有了头结点以后,首元结点实际为链表的第二个结点,可以使得在添加删除的操作上更具有统一性
缺点: 会多出一个不必要的空间


1 Example1 有头结点

// 题目大意:删除,值为val的结点(单次删除), 并返回头结点
public ListNode removeElement(ListNode head, int val) {
        if(head.next==null) return head;//空链表
        ListNode pre = head, p = head.next;
        while(p.val!=val&&p.next!=null) {
                pre = p;
                p = p.next;
        }
        if(p.val==val) {
            pre.next = p.next;
        }else {
        	//此链表无,值为val的结点
        }
        return head;
    }
}

1 Example2 无头结点

// solution 1 使用上面 "Example1 无头结点"的解法,最后再处理head ---> Acceted / Used
public ListNode removeElements(ListNode head, int val) {
        if(head==null) return head;//空链表
        ListNode pre = head, p = head.next;
        if(p!=null) {
            while(p.val!=val&&p.next!=null) {
                pre = p;
                p = p.next;
            }
            if(p.val==val) {
                pre.next = p.next;
                return head;
            }else {
            	//此链表无,值为val的结点
            }
        }
        if(head.val==val) head = head.next;//最后判断头结点
        return head;
    }
}
//solution 2 
public ListNode removeElements(ListNode head, int val) {
        if(head==null) return head;//空链表
        ListNode p = head, pre;
        while(p.val!=val&&p.next!=null) {
            pre = p;
            p = p.next;
        }
        if(p.val==val) {
        	if(p==head) {// 多次此处的条件,相比于 "Example1 无头结点"
        		return head = p.next;
        	}else {
            	pre.next = p.next;
        	}
        }else {
        	//此链表无,值为val的结点
        }
        return head;
    }
}

1 Example3 无头结点(删除链表中所有值为val的结点)

//Solution 1 迭代 ---> 根据上面"Example2 无头结点 solution 1" 拓展使用 --->Acceted / Used
// 耗时 O(n),空间O(1)
public ListNode removeElements(ListNode head, int val) {
        if(head==null) return head;//空链表
        ListNode pre = head, p = head.next;
        while(p!=null) {
            while(p.val!=val&&p.next!=null) {
                pre = p;
                p = p.next;
            }
            if(p.val==val) {
                pre.next = p.next;
            }else {
            	//此链表无,值为val的结点
            }
            p = p.next;
        }
        if(head.val==val) head = head.next;//最后判断头结点
        return head;
    }
}

//Solution 2 递归 --->Acceted 时空都是O(n),
// 
public ListNode removeElements(ListNode head, int val) {
	if(head==null) {
		return head;
	}
	head.next = removeElements(head.next,val);//当前结点只需要考虑下一个节点即可,递归即可
	return head.val==val?head.next:head;//从后面开始判断,返回head/head.next 即可
}

//Solution 3 官方:构造有头结点的链表 ---> (Acceted / Used) Optimally 
//题解链接https://leetcode.cn/problems/remove-linked-list-elements/solution/yi-chu-lian-biao-yuan-su-by-leetcode-sol-654m/
// 耗时 O(n),空间O(1)
public ListNode removeElements(ListNode head, int val) {
	ListNode pre = new ListNode(0);
	pre.next = head;
	ListNode temp = pre;
	while(temp.next!=null) {
		if(temp.next.val==val) {
			temp.next = temp.next.next;//指针指向
		}else {
			temp = temp.next;//指针指向
		}
	}
	return pre.next;
}

//(含头结点)单链表的节点删除,增加—最易犯错!!!
https://blog.csdn.net/weixin_46273997/article/details/106087607

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值