记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
5/4 48. 旋转图像
位置变化i,j => j,n-1-i
python
def rotate(matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
s = set()
for i in range(n):
for j in range(n):
pre = float('inf')
x,y = i,j
while (x,y) not in s:
if pre==float('inf'):
pre = matrix[x][y]
x,y = y,n-1-x
continue
matrix[x][y],pre = pre,matrix[x][y]
s.add((x,y))
x,y = y,n-1-x
return
5/5 61. 旋转链表
把链表向右旋转 k 位,等价于把末尾的 k 个节点移到前面。
先遍历一次得到链表长度 n 和尾节点 tail。
若 n 为 0 或 1,或 k % n == 0,链表不变。
1 令 k = k % n,避免无效的大旋转。
2 把尾节点连到头节点,形成环。
3 新头节点是原链表第 (n - k) 个节点的下一个;
新尾节点是原链表第 (n - k) 个节点。
4 将新尾节点 next 断开,恢复为普通链表。
python
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def rotateRight(head, k):
"""
:type head: Optional[ListNode]
:type k: int
:rtype: Optional[ListNode]
"""
if not head or not head.next or k == 0:
return head
# 计算长度并找到尾节点
n = 1
tail = head
while tail.next:
tail = tail.next
n += 1
k %= n
if k == 0:
return head
# 成环
tail.next = head
# 找到新尾节点(第 n-k 个节点)
steps = n - k
new_tail = head
for _ in range(steps - 1):
new_tail = new_tail.next
# 断环得到新头
new_head = new_tail.next
new_tail.next = None
return new_head
5/6 1861. 旋转盒子
对于每一行 从后往前遍历 如果遇到石头 则将石头移动到最右端
如果遇到障碍物 则将石头移动到障碍物后面
如果遇到空格 则继续遍历
最后将每一行旋转90度
python
def rotateTheBox(boxGrid):
"""
:type boxGrid: List[List[str]]
:rtype: List[List[str]]
"""
n=len(boxGrid)
m=len(boxGrid[0])
for i in range(n):
# p 表示当前石头可落到的最右空位
p = m - 1
for j in range(m - 1, -1, -1):
if boxGrid[i][j] == '*':
# 遇到障碍物,下一段重新计算可落点
p = j - 1
elif boxGrid[i][j] == '#':
# 石头尽量往右落到 p
if j != p:
boxGrid[i][p] = '#'
boxGrid[i][j] = '.'
p -= 1
ans = [[0]*n for _ in range(m)]
for i in range(n):
for j in range(m):
ans[j][n-1-i]=boxGrid[i][j]
return ans
5/7 3660. 跳跃游戏 IX
当前位置i
premax[i] 表示区间 [0, i] 的最大值
从后往前遍历
sufmin 表示已遍历过的区间 [i, n-1] 的最小值
对于位置i
如果位置i是最后一个位置 或者premax[i] <= sufmin[i]
说明不能借助右侧更小值扩展可以达到的地方 答案为premax[i]
否则 说明可以通过右跳小值+左跳大值达到i+1的可达集合 答案为ans[i+1]
python
def maxValue(nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
n = len(nums)
ans = [0] * n
# pre_max[i] 表示区间 [0, i] 的最大值
pre_max = [0] * n
pre_max[0] = nums[0]
for i in range(1, n):
pre_max[i] = max(pre_max[i - 1], nums[i])
# suf_min 表示当前位置右侧(含已遍历部分)的最小值
suf_min = float("inf")
for i in range(n - 1, -1, -1):
# i == n-1 时没有 i+1,答案只能是 pre_max[i]
if i == n - 1 or pre_max[i] <= suf_min:
ans[i] = pre_max[i]
else:
# 当 pre_max[i] > suf_min 时,可连通到 i+1 的可达集合
ans[i] = ans[i + 1]
suf_min = min(suf_min, nums[i])
return ans
5/8 3629. 通过质数传送到达终点的最少跳跃次数
将所有数值的位置记录下来
BFS
标记已经到过的位置
对于当前处理值 如果是质数 将它的所有未达到过的倍数放入下一步处理的list中
python
def minJumps(nums):
"""
:type nums: List[int]
:rtype: int
"""
from collections import defaultdict, deque
n = len(nums)
if n <= 1:
return 0
max_v = max(nums)
# 最小质因子筛:spf[x] = x 的最小质因子
spf = list(range(max_v + 1))
for i in range(2, int(max_v ** 0.5) + 1):
if spf[i] == i: # i 是质数
start = i * i
for j in range(start, max_v + 1, i):
if spf[j] == j:
spf[j] = i
# 记录每个质因子对应的所有下标(nums[idx] 能被该质因子整除)
prime_to_indices = defaultdict(list)
for idx, val in enumerate(nums):
x = val
while x > 1:
p = spf[x]
prime_to_indices[p].append(idx)
while x % p == 0:
x //= p
# BFS 最短路
dist = [-1] * n
dist[0] = 0
q = deque([0])
used_prime = set() # 同一个质数的传送边只展开一次
while q:
i = q.popleft()
step = dist[i] + 1
if i == n - 1:
return dist[i]
# 相邻跳跃
if i - 1 >= 0 and dist[i - 1] == -1:
dist[i - 1] = step
q.append(i - 1)
if i + 1 < n and dist[i + 1] == -1:
if i + 1 == n - 1:
return step
dist[i + 1] = step
q.append(i + 1)
# 质数传送:仅当 nums[i] 本身是质数时可用
p = nums[i]
if p > 1 and spf[p] == p and p not in used_prime:
used_prime.add(p)
for j in prime_to_indices[p]:
if dist[j] == -1:
if j == n - 1:
return step
dist[j] = step
q.append(j)
return -1
5/9
python
5/10
python