LeetCode 每周算法 3(矩阵、链表)
矩阵算法:
class Solution(object):
def setZeroes(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
# 如果矩阵为空或没有列,则直接返回
if not matrix or not matrix[0]:
return
# 获取矩阵的行数和列数
rows, cols = len(matrix), len(matrix[0])
# 初始化两个标志变量,用于记录第一行和第一列是否需要设置为0
firstRowZero = False
firstColZero = False
# 遍历第一行,检查是否有0
for j in range(cols):
if matrix[0][j] == 0:
firstRowZero = True
break
# 遍历第一列,检查是否有0
for i in range(rows):
if matrix[i][0] == 0:
firstColZero = True
break
# 遍历矩阵(除了第一行和第一列),标记0所在的行和列
for i in range(1, rows):
for j in range(1, cols):
if matrix[i][j] == 0:
matrix[i][0] = 0 # 在第一列标记行
matrix[0][j] = 0 # 在第一行标记列
# 根据第一行和第一列的标记,设置对应的行和列为0
for i in range(1, rows):
for j in range(1, cols):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
# 如果第一行有0,则将第一行所有元素设置为0
if firstRowZero:
for j in range(cols):
matrix[0][j] = 0
# 如果第一列有0,则将第一列所有元素设置为0
if firstColZero:
for i in range(rows):
matrix[i][0] = 0
class Solution(object):
def spiralOrder(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: List[int]
"""
if not matrix or not matrix[0]:
# 如果矩阵为空或没有列,则直接返回空列表
return []
rows, cols = len(matrix), len(matrix[0])
# 初始化矩阵的边界
top, bottom = 0, rows - 1
left, right = 0, cols - 1
result = []
while top <= bottom and left <= right:
# 从左到右遍历上边界
for i in range(left, right + 1):
result.append(matrix[top][i])
top += 1 # 上边界下移
# 从上到下遍历右边界
for i in range(top, bottom + 1):
result.append(matrix[i][right])
right -= 1 # 右边界左移
# 如果已经遍历完整个矩阵,则跳出循环
if top > bottom or left > right:
break
# 从右到左遍历下边界
for i in range(right, left - 1, -1):
result.append(matrix[bottom][i])
bottom -= 1 # 下边界上移
# 从下到上遍历左边界
for i in range(bottom, top - 1, -1):
result.append(matrix[i][left])
left += 1 # 左边界右移
return result
class Solution(object):
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
# 第一步:沿主对角线镜像对称
for i in range(n):
for j in range(i, n): # 注意 j 从 i 开始,避免重复交换
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
# 第二步:反转每一行
for i in range(n):
matrix[i] = matrix[i][::-1]
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 如果矩阵为空或者矩阵的第一行为空,则直接返回False,表示找不到目标值。
if not matrix or not matrix[0]:
return False
# 获取矩阵的行数和列数。
m, n = len(matrix), len(matrix[0])
# 初始化搜索的起始位置为矩阵的右上角。
row, col = 0, n - 1
# 当行索引小于行数且列索引大于等于0时,继续搜索。
while row < m and col >= 0:
# 如果当前位置的值等于目标值,返回True,表示找到了目标值。
if matrix[row][col] == target:
return True
# 如果当前位置的值小于目标值,说明目标值在当前位置的下方,因此行索引下移。
elif matrix[row][col] < target:
row += 1
# 如果当前位置的值大于目标值,说明目标值在当前位置的左侧,因此列索引左移。
else:
col -= 1
# 如果循环结束还没有找到目标值,则返回False。
return False
链表算法:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
# 如果任一链表为空,则它们不可能相交,直接返回 None
if not headA or not headB:
return None
pA = headA # 初始化指针 pA 指向链表 A 的头节点
pB = headB # 初始化指针 pB 指向链表 B 的头节点
# 当 pA 和 pB 不相等时,继续循环
while pA != pB:
# 如果 pA 到达链表 A 的末尾(即 pA 为 None),则将 pA 指向链表 B 的头节点
pA = pA.next if pA else headB
# 如果 pB 到达链表 B 的末尾(即 pB 为 None),则将 pB 指向链表 A 的头节点
pB = pB.next if pB else headA
# 当循环结束时,pA 和 pB 一定相等,它们要么都指向相交节点,要么都指向 None(如果不相交)
return pA
# 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
"""
# 初始化前一个节点为None
prev = None
# 初始化当前节点为头节点
current = head
# 遍历链表
while current:
# 保存当前节点的下一个节点
next_temp = current.next
# 将当前节点指向前一个节点,实现反转
current.next = prev
# 将前一个节点移动到当前节点
prev = current
# 将当前节点移动到下一个节点
current = next_temp
# 返回反转后的头节点,即最后一个处理的节点
return prev
# 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 isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
# 边界条件:如果链表为空或只有一个节点,则一定是回文链表
if not head or not head.next:
return True
# 使用快慢指针找到链表的中点
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 反转链表的后半部分
prev, current = None, slow
while current:
next_temp = current.next
current.next = prev
prev = current
current = next_temp
# 比较链表的前半部分和反转后的后半部分是否相等
left, right = head, prev
while right:
if left.val != right.val:
return False
left = left.next
right = right.next
# 如果全部节点都比较完毕且相等,则返回True
return True
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
# 初始化快慢指针,都指向头节点
slow = head
fast = head
# 当快指针和快指针的下一个节点都不为空时,循环继续
while fast and fast.next:
# 慢指针每次移动一步
slow = slow.next
# 快指针每次移动两步
fast = fast.next.next
# 如果快慢指针相遇,说明链表中有环
if slow == fast:
return True
# 如果循环结束,说明快指针已经到达链表尾部,链表中无环
return False
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 如果链表为空或只有一个节点,则肯定没有环
if not head or not head.next:
return None
# 初始化快慢指针,都指向头节点
slow = head
fast = head
# 查找快慢指针相遇的点
while fast and fast.next:
slow = slow.next # 慢指针每次移动一步
fast = fast.next.next # 快指针每次移动两步
# 如果快慢指针相遇,则存在环
if slow == fast:
break
# 如果快指针已经到达链表末尾(fast 或 fast.next 为空),则不存在环
if not fast or not fast.next:
return None
# 将慢指针重新放回头节点,快指针保持在相遇点
slow = head
# 移动快慢指针,每次一步,直到它们再次相遇
while slow != fast:
slow = slow.next
fast = fast.next
# 返回环的起始节点
return slow