83. 删除排序链表中的重复元素
- 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例:
输入: 1->1->2->3->3
输出: 1->2->3
思路:
- 考虑特殊情况——链表为空,直接返回。
- 使用一个指针,将指针next的值与当前值进行判断,若相等,将next再向后指一位。
- 若不想等,指针向后移动到不相等的位置。
代码实现
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
# 链表为空时,直接返回
if head is None:
return head
l = head
while l.next:
if l.next.val == l.val:
l.next = l.next.next
else:
l = l.next
return head
203. 移除链表元素
- 删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
思路:
想要删除某个节点,就必须找到这个节点的前一个节点,把前一个节点的指针改变,即指向下下一个就可以达到删除的目的了。
代码实现1
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
l = ListNode(-1)
l.next = head
pre, cur = l, l.next
while cur:
if cur.val == val:
cur = cur.next
else:
pre.next = cur
cur = cur.next
pre = pre.next
pre.next = None
return l.next
代码实现2
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
p = ListNode(-1)
# 因为要删除的可能是链表的第一个元素,所以用一个h节点来做处理
# 最后只要返回h的下一个节点即可
p.next,h = head,p
# 注意遍历的条件是p.next不为空
while p.next:
# 如果p的下一个节点的值==val
# P就指向下下一个,这就删掉了指定的节点
if p.next.val==val:
p.next = p.next.next
# 注意这里的continue
# 因为循环最后还有一个P=p.next,所以要跳过
continue
# 不用continue用else的方式也是可以的
p = p.next
return h.next
19. 删除链表的倒数第N个节点
- 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2. 给定的 n 保证是有效的。
当删除了倒数第二个节点后,链表变为 1->2->3->5.
思路1:两次遍历
- 先遍历一次链表,求出链表的总长度。
- 根据总长度-n,计算出要删除节点的位置。
- 第二次遍历的时候,在要删除的节点的前一个节点处,将此节点的next指针指向next.next节点,达到删除节点的目的。
代码实现
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 增加特殊节点,处理要删除的节点位于首节点的情况
h = ListNode(-1)
# 将特殊节点连接到head上,且放置游标指针于head上,作计算链表长度使用
h.next, cur = head, head
# 定义第二次遍历时的指针,放置到特殊节点位置,最终需要返回特殊节点的next节点
l = h
length = 0
# 第一次遍历,求得列表长度
while cur:
cur = cur.next
length += 1
# 找到要删除节点的位置
node = length-n
# 若要删除的节点位于链表中或链表尾,则通过循环将l移动到要删除节点的前一个节点
while node > 0:
l = l.next
node -= 1
# 此处处理两种情况
# 一、要删除的节点位于首节点(即node=0),将首节点的next指针指向next.next节点
# 二、退出循环后,l节点位于要删除节点的前一个节点,将此节点的next指针指向next.next节点,完成删除
l.next = l.next.next
return h.next
思路2:一次遍历
- 定义两个指针pre和cur,cur先走n步,接着pre和cur同时往前走,当cur指针走到链表末尾时,pre指针刚好走到要删除的节点的前一个位置。
- 将pre节点的next指针指向next.next节点,就可以完成删除操作了。
代码实现
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 增加特殊节点,处理要删除的节点位于首节点的情况
h = ListNode(-1)
h.next = head
# 定义两个指针pre和cur
pre = h
cur = head
while cur:
# cur指针先走n步,此时,cur处于要删除节点的后一个节点
if n > 0:
cur = cur.next
n -= 1
continue
# cur和pre同时向前走,cur走到头时(cur = None),pre位于要删除节点的前一个节点,退出循环
cur = cur.next
pre = pre.next
# 将pre节点的next指针指向next.next节点,完成删除操作
pre.next = pre.next.next
return h.next