代码随想录算法训练营第三天|leetcode 203. 移除链表元素 707. 设计链表 206. 反转链表

链表理论基础

链表理论基础
链表的类型:单链表,双链表,循环链表
链表的定义:

class ListNode:
    def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next

链表的增删:O(1),查询:O(n)
数组的增删:O(n),查询:O(1)

leetcode 203. 移除链表元素

链表移除元素:找到这个节点的前一个节点,让前一个节点指向这个节点的下一个节点

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        # 虚拟头结点
        dummyhead = ListNode()
        dummyhead.next = head   # 让虚拟头结点指向链表的头结点
        cur = dummyhead
        while cur.next != None:
            if cur.next.val == val:    # 注意只能删cur.next不能删cur,因为找不到cur的前一个节点
                cur.next = cur.next.next
            else:
                cur = cur.next 
        return dummyhead.next   # 注意返回的是虚拟头结点的下一个节点
                                # 而不是head,因为原链表的head可能已经被我们删除了

leetcode 707. 设计链表

链表的增删改查
需要注意的地方:

  1. 需要自己定义一个链表类,dummyhead作为成员变量,定义一个num记录链表的元素个数,后面调用dummyhead和num时,都需要使用self.dummyhead和self.num,在成员函数里调用别的成员函数时也需要加上self.
  2. while循环的截止条件里的index,在查询操作时可以等于0,因为此时找的就是index对应的节点,而增删操作时只能大于0,因为增删找的是index对应节点的前一个节点,这样才能把index对应的节点删掉
class ListNode:

    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class MyLinkedList:

    def __init__(self):
        self.dummyhead = ListNode()
        self.num = 0

    def get(self, index):
        if index < 0 or index > self.num:
            return -1
        else:
            cur = self.dummyhead
            while cur.next is not None and index >= 0:  # 这里包含等号是因为就是要找index对应的元素
                cur = cur.next                          # 而不是index的上一个元素
                index -= 1
            return cur.val

    def addAtHead(self, val):
        node = ListNode(val)
        tmp = self.dummyhead.next    # 注意,需要用tmp来保存真正的头结点
        self.dummyhead.next = node
        node.next = tmp
        self.num += 1

    def addAtTail(self, val):
        node = ListNode(val)
        cur = self.dummyhead
        while cur.next is not None:
            cur = cur.next
        cur.next = node
        self.num += 1

    def addAtIndex(self, index, val):
        node = ListNode(val)
        if index == self.num:
            self.addAtTail(val)
            return
        if index < 0:
            self.addAtHead(val)
            return
        if index > self.num:
            return
        cur = self.dummyhead
        while cur.next is not None and index > 0:  # 不包含等号找的是index的上一个元素
            cur = cur.next
            index -= 1
        tmp = cur.next
        cur.next = node
        node.next = tmp
        self.num += 1

    def deleteAtIndex(self, index):
        if 0 <= index < self.num:
            cur = self.dummyhead
            while cur.next is not None and index > 0:
                cur = cur.next
                index -= 1
            cur.next = cur.next.next
            self.num -= 1
        else:
            return

leetcode 206. 反转链表

需要注意的地方:

  1. 如何实现反转链表?其实就是依次让节点指向它的前一个节点
  2. 所以考虑双指针法,cur用来代表当前节点,pre用来代表cur的前一个节点,令 cur.next = pre,就可以实现翻转方向的操作
  3. cur初始化为原链表的头结点head,pre是cur的前一个节点,由于翻转后,原始的头结点会变成尾结点,尾结点指向null,所以给pre初始化为null
  4. 令cur.next = pre后,cur指向pre,此时cur和它原本的下一个节点之间的连接断掉了,相当于cur与之后的链表都失去了连接,所以必须先用一个临时指针temp去保存cur.next,然后才能进行翻转的操作
  5. 每次翻转完, 都需要让两个指针右移,所以让pre = cur, cur = temp
  6. 最后cur指向null,而pre就是新链表的头结点
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # 双指针法
        cur = head
        pre = None
        while cur is not None:
            temp = cur.next   # 要用临时指针保留cur.next的值 不然就找不到下一个节点了
            cur.next = pre  # 翻转方向
            pre = cur
            cur = temp
        return pre   # pre最后会成为新的头结点
        # 递归法
        def reverse(cur, pre):
            if cur == None:   # 递归的终止条件
                return pre    # 返回反转后的头结点
            temp = cur.next   # 同样需要保存cur.next,不然就找不到了
            cur.next = pre
            return reverse(temp, cur) # 递归调用自身,令cur和pre右移,注意这里要return!不然输出结果是空值
        return reverse(head, None)  # 初始化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值