[leetcode_203]203. 移除链表元素

203. 移除链表元素

https://leetcode-cn.com/problems/remove-linked-list-elements/

难度简单502收藏分享切换为英文接收动态反馈

删除链表中等于给定值 val 的所有节点。

示例:

输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5

解法1 蛮力操作 删除

为了方便测试给出一些辅助测试函数

create_linked_list 创建链表

print_linked_list 打印链表

from typing import List, Optional

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


def create_linked_list(array: List, n: int) -> Optional[ListNode]:
    """

    :param array: linked list node value
    :param n: length of array
    :return:
    """
    if not array:
        return None

    head = ListNode(array[0])
    p = head
    for i in range(1, n):
        p.next = ListNode(array[i])
        p = p.next
    return head


def print_linked_list(head: ListNode):
    while head:
        print(f'{head.val} ->', end=' ')
        head = head.next
    print('NULL')


删除的元素如果就是头节点的情况,需要单独的考虑。

删除头节点的情况

img1

删除任意节点的情况

img02

下面给出解题代码 :

第一种暴力解法
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        # 处理头结点 是要删除的节点的情况
        while head and head.val == val:
            delnode= head
            head = delnode.next

        # 开始删除 头结点的下一个节点
        cur = head
        while cur and cur.next:
            if cur.next.val == val:
                delnode = cur.next
                cur.next = delnode.next
                del delnode
            else:
                cur = cur.next
        return head

第二种暴力解法:

相对第一种解法 : 类似,只是 删除节点的 判断条件 稍微变化了一下。

因为 我们需要找到 cur.next 的值 是不是等于val , 所以while 的条件 进来的时候 ,就判断cur.next 是否存在即可。这里不需要担心 cur 这个节点是否为空的问题, 因为前面处理完head节点了。 head 节点不可能为空值。

这里要好好体会下, 如果有效的进行控制判断条件。这种写法看起来更加精妙。

一般我们在 链表中如果访问一个结点, 就需要进行判定空的判断, 否则很容易出现. 访问了一个空节点的next 的这种情况。 类似 if cur and cur.next 判断,否则 很容易出现访问空节点的情况。


class Solution:
    """
     头结点 暴力删除
    """

    def removeElements(self, head: ListNode, val: int) -> ListNode:

        # 处理头结点 是要删除的节点的情况
        while head is not None and head.val == val:
            delnode = head
            head = delnode.next

        # 处理完成后,继续判断 head 是否为空
        if head is None:
            return None

        # 开始删除 头结点的下一个节点
        cur = head
        while cur.next:
            if cur.next.val == val:
                delnode = cur.next
                cur.next = delnode.next
            else:
                cur = cur.next

        return head


if __name__ == '__main__':
    # array = [1, 1, 1, 2, 3, 1, 1, 4, 5, 6, 1,1]
    array = [1, 1, 1]

    head = create_linked_list(array=array, n=len(array))

    print_linked_list(head)

    h2 = Solution().removeElements(head, 1)

    print_linked_list(h2)

解法2 建立虚拟头节点

通过建立虚拟头节点 ,保证链表的删除的操作是统一的. 防止 删除的结点刚好在头节点上, 要进行特殊的处理。

有了虚拟头结点, 我们处理链表 就不需要考虑是不是 删除的节点是否在头节点

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None


class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        # 构建虚拟头节点
        dummy_head = ListNode('dummy')
        dummy_head.next = head
       
        cur = dummy_head

        while cur.next:
            if cur.next.val == val:
                delnode = cur.next
                cur.next = delnode.next
                del delnode
            else:
                cur = cur.next
			
        result = dummy_head.next
        # 删除虚拟头节点
        del dummy_head
        return result

解法3 递归法

本着 万事皆可递归的原则 ,链表本身就是一种可递归的结构,和二叉树相比较而言,只是链表只有一个next 指针,而二叉树有两个指针而已.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None


class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        # terminator
        if head is None:
            return None

        # drill down
        head.next = self.removeElements(head.next, val)

        # current level logic process
        if head.val == val:
            return head.next
        else:
            return head
分享快乐,留住感动. '2021-06-05 10:37:35' --frank
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值