class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
seen = set() # 哈希集合
# seen = {} # 哈希字典
cur = head
while cur:
if cur in seen: # 有重复的节点则有环
return True
seen.add(cur) # 直接存节点
# seen[cur] = True # 将节点作为键,值设为True
cur = cur.next
return False
快慢指针
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow = fast = head # 乌龟和兔子同时从起点出发
while fast and fast.next:
slow = slow.next # 乌龟走一步
fast = fast.next.next # 兔子走两步
if fast == slow: # 兔子追上乌龟(套圈),说明有环
return True
return False # 访问到了链表末尾,无环
142. 环形链表 II - 力扣(LeetCode)
快慢指针
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if slow == fast: # 快慢指针相遇,s走了nb,f走了2nb
fast = head # 入口处需要a+nb,s已经走了nb
while fast != slow: # 同时走a就可到达入口
fast = fast.next
slow = slow.next
return fast
return None
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if list1 is None:
return list2
if list2 is None:
return list1
if list1.val < list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list2.next, list1)
return list2
2. 两数相加 - 力扣(LeetCode)
模拟——转数字
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# 链表转化为数字
def getNum(head):
num = 0
flag = 1
while head != None:
num += head.val * flag
head = head.next
flag *= 10
return num
# 计算和
twoSum = getNum(l1) + getNum(l2)
# 和为0直接返回0节点
if twoSum == 0:
return ListNode(0)
# 循环生成新链表
head = cur = ListNode(-1)
while twoSum != 0:
cur.next = ListNode(twoSum % 10)
cur = cur.next
twoSum //= 10 # 整除
return head.next
模拟——进位
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 创建一个结点值为 None 的头结点, dummy 和 p 指向头结点, dummy 用来最后返回, p 用来遍历
dummy = p = ListNode(None)
s = 0 # 初始化进位 s 为 0
while l1 or l2 or s:
# 如果 l1 或 l2 存在, 则取l1的值 + l2的值 + s(s初始为0, 如果下面有进位1, 下次加上)
s += (l1.val if l1 else 0) + (l2.val if l2 else 0)
p.next = ListNode(s % 10) # p.next 指向新链表, 用来创建一个新的链表
p = p.next # p 向后遍历
s //= 10 # 有进位情况则取模, eg. s = 18, 18 // 10 = 1
l1 = l1.next if l1 else None # 如果l1存在, 则向后遍历, 否则为 None
l2 = l2.next if l2 else None # 如果l2存在, 则向后遍历, 否则为 None
return dummy.next # 返回 dummy 的下一个节点, 因为 dummy 指向的是空的头结点, 下一个节点才是新建链表的后序节点
递归——进位
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
def dfs(l, r, i):
# 终止条件:都为空节点且进位为0
if not l and not r and not i: return None
s = (l.val if l else 0) + (r.val if r else 0) + i
node = ListNode(s % 10) # 当前节点
node.next = dfs(l.next if l else None, r.next if r else None, s // 10) # 接上递归链表
return node
return dfs(l1, l2, 0)
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
双指针
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(0, head) # 直接创建虚拟头节点
fast = slow = dummy # 双指针
# 快指针先走
while n != 0:
fast = fast.next
n -= 1
# 双指针一起走直到fast到底
while fast.next != None:
fast = fast.next
slow = slow.next
# 删除节点
slow.next = slow.next.next
return dummy.next
24. 两两交换链表中的节点 - 力扣(LeetCode)
模拟
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, head)
cur = dummy
while cur.next and cur.next.next:
pre = cur
cur = cur.next
temp = cur.next.next
pre.next = cur.next # 步骤1
pre.next.next = cur # 步骤2
cur.next = temp # 步骤3
return dummy.next
递归
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 终止条件:如果剩0/1个节点,无法交换,直接返回
if not head or not head.next:
return head
# 交换头两个结点
newhead = head.next
head.next = self.swapPairs(newhead.next) # 接上后面交换好的结果
newhead.next = head
return newhead
第五届管理科学与工程管理国际学术会议(ICMSEM 2024)
2024 5th International Conference on Management Science and Engineering Management
第五届管理科学与工程管理国际学术会议 (ICMSEM 2024)将于2024年6月07-09日于中国沈阳召开。会…