数据结构与算法之链表

这篇博客探讨了链表作为数据结构的应用,包括LeetCode中两链表逆序相加的问题,以及链表的反转、部分反转、环形链表的检测和处理等操作。涉及算法实现和关键技巧,如快慢指针法。此外,还讨论了如何处理链表中的重复元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表是一种数据结构,可以通过链表的指针,得到所属的值和next的指针。

Leetcode2,Leetcode445 关于链表的两数相加.

'''
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
'''
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        result = ListNode(0)
        val = l1.val+l2.val
        # 判断是否大于10
        cur_add = 1 if val >= 10 else 0
        result.val = val % 10 if val >= 10 else val
        pre = result
        while (l1 is not None) or (l2 is not None):
            l1 = l1.next if l1 else None
            l2 = l2.next if l2 else None
            if l1 or l2:
                cur = ListNode(0)
                # 补全链表 如果链表为空
                l1_val = l1.val if l1 else 0
                l2_val = l2.val if l2 else 0
                # 计算当前链表的值并且判断是否大于10
                val = cur_add + l1_val + l2_val
                cur_add = 1 if val >= 10 else 0
                cur.val = val % 10 if val >= 10 else val

                # 将当前节点连接到result.next
                pre.next = cur
                pre = cur
            else:
                break

        if cur_add:
            pre.next = ListNode(1,None)
        return result

Leetcode445 不是逆序的,所以要将链表旋转。就变成逆序相加。再把结果旋转回去。

旋转链表是Leetcode206.

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

输入:head = [1,2]
输出:[2,1]

输入:head = []
输出:[]
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = None
        cur = head
        while cur:
            # 记录当前节点的下一个节点
            tmp = cur.next
            # 然后将当前节点指向pre
            cur.next = pre
            # pre,cur和 cur,tmp交换
            pre, cur = cur, tmp
        return pre

旋转链表还可以旋转部分链表。

class Solution:
    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        # 放置一个哑节点,指向head
        dummy_node = ListNode(-1)
        dummy_node.next = head
        pre = dummy_node

        # 在left之前的节点都不需要翻转
        for _ in range(left - 1):
            pre = pre.next

        # current 是 pre的下一个节点
        cur = pre.next
        for _ in range(right - left):
            # next的节点 实际要前移
            next = cur.next
            # next.next 指向 current.next,current 往后移动
            cur.next = next.next
            # next.next 指向 pre.next,next往前移动
            next.next = pre.next
            # pre.next 指向 next,相当于吧current后面一个往前。
            pre.next = next
        return dummy_node.next

分链表。给定left和right,反转left和right中间。

除了单向链表,还有环形链表。

环形链表如何判断:主要通过快慢指针。

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if (head == None) or (head.next == None): return False
        slow = head
        fast = head
        # 当快慢指针同步的时候.  证明有环
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return False

以及如何判断环的初始节点位置,需要通过快慢指针,两次相遇即可。

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if (head is None) or (head.next is None): return

        slow = head
        fast = head
        while True:
            if not (fast and fast.next): return
            fast = fast.next.next
            slow = slow.next
            if fast == slow: break

        fast = head
        while fast != slow:
            fast = fast.next
            slow = slow.next
        return fast

以及判断环的长度,从第一次相遇到第二次相遇,慢指针比快指针少走一圈。

class Solution:
    def CycleLen(self, head: ListNode) -> ListNode:
        if (head is None) or (head.next is None): return
        ct =  0
        slow = head
        fast = head
        while True:
            if not (fast and fast.next): return ct
            fast = fast.next.next
            slow = slow.next
            if fast == slow: break
        
        ct = 1
        fast = fast.next.next
        slow = slow.next
        while fast != slow:
            fast = fast.next.next
            slow = slow.next
            ct += 1
        return ct

以及移除链表重复元素:

class Solution:
    def removeDuplicateNodes(self, head: ListNode) -> ListNode:
        pre = ListNode(-1)
        pre.next = head
        cur = head

        # 记载节点
        nodes = set()
        while cur:
            if cur.val not in nodes:
                nodes.add(cur.val)
                pre, cur = pre.next, cur.next
            else:
                cur = cur.next
                pre.next = cur.next
        return head

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值