记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
4/6 874. 模拟行走机器人
模拟四个方向 判断每次走一步是否遇到障碍物
如果障碍物则不动
python
def robotSim(commands, obstacles):
"""
:type commands: List[int]
:type obstacles: List[List[int]]
:rtype: int
"""
step = [[0,1],[1,0],[0,-1],[-1,0]]
d = 0
cx,cy=0,0
m = set([(x[0],x[1]) for x in obstacles])
ans = 0
for c in commands:
if c<0:
if c==-1:
d+=1
else:
d-=1
d%=4
else:
for i in range(c):
if (cx+step[d][0],cy+step[d][1]) in m:
break
cx,cy=cx+step[d][0],cy+step[d][1]
ans = max(ans,cx*cx+cy*cy)
return ans
4/7 2069. 模拟行走机器人 II
机器人始终沿矩形边界行走,因此可把运动看成"周长环"上的位置变化。
1 周长(边界步数):
p = 2 * (width + height) - 4
2 用 self.k 记录在边界上前进的总步数(对 p 取模)。
3 step(num) 只需做:
self.k = (self.k + num) % p
同时记录是否发生过移动(self.moved),用于处理特殊方向。
4 getPos():
根据 self.k 在四条边上的区间,O(1) 映射到 (x, y)。
5 getDir():
同样按 self.k 所在边返回方向。
但有一个关键特判:
-当 self.k == 0 且发生过移动时,位置回到 (0,0),方向应为 "South"
-初始尚未移动时方向是 "East"
python
class Robot(object):
def __init__(self, width, height):
"""
:type width: int
:type height: int
"""
self.width = width
self.height = height
self.p = 2 * (width + height) - 4
self.k = 0
self.moved = False
def step(self, num):
"""
:type num: int
:rtype: None
"""
if num == 0:
return
self.moved = True
self.k = (self.k + num) % self.p
def getPos(self):
"""
:rtype: List[int]
"""
k = self.k
w = self.width
h = self.height
if k < w:
return [k, 0]
k -= w - 1
if k < h:
return [w - 1, k]
k -= h - 1
if k < w:
return [w - 1 - k, h - 1]
k -= w - 1
return [0, h - 1 - k]
def getDir(self):
"""
:rtype: str
"""
k = self.k
w = self.width
h = self.height
e = w - 1
n = h - 1
ww = w - 1
if k == 0:
return "South" if self.moved else "East"
if k <= e:
return "East"
if k <= e + n:
return "North"
if k <= e + n + ww:
return "West"
return "South"
4/8 3653. 区间乘法查询后的异或 I
模拟
对于每个查询 [l, r, k, v]:
- 从 idx = l 开始
- 每次让 idx += k,直到 idx > r
- 对经过的位置执行 nums[idx] = nums[idx] * v % MOD
全部查询处理后,再把整个 nums 做一次按位异或得到答案。
python
def xorAfterQueries(nums, queries):
"""
:type nums: List[int]
:type queries: List[List[int]]
:rtype: int
"""
MOD = 10**9 + 7
for l, r, k, v in queries:
for idx in range(l, r + 1, k):
nums[idx] = (nums[idx] * v) % MOD
ans = 0
for x in nums:
ans ^= x
return ans
4/9 3655. 区间乘法查询后的异或 II
一次查询会修改这些位置:
l, l+k, l+2k, ... , <= r
如果每个查询都直接逐个位置去乘,数据大时会超时。
所以我们按 k 的大小分类:
- k 很大:
一次查询真正会修改的位置很少,可以直接暴力更新。 - k 很小:
这时查询很多、每次影响的位置也多,不能再暴力。
我们把下标按 %k 的结果分组。
例如 k=3 时,分成:
0,3,6,9,...
1,4,7,10,...
2,5,8,11,...
对某个查询 [l, r, k, v] 来说,它只会落在其中一组里,
并且在这一组中对应的是"连续一段都乘 v"。
于是我们在这一组上做乘法差分:- 段的开头乘 v,表示从这里开始生效
- 段结束后的下一位乘 inv(v),表示从这里开始取消影响
这里的 inv(v) 就是 v 在模 MOD 下的乘法逆元。
你可以把它理解成"模意义下的除以 v"。
因为这里不能直接做除法,所以要用逆元来抵消前面乘进去的 v。
最后,把所有位置更新完,再对整个数组求异或。
python
def xorAfterQueries(nums, queries):
"""
:type nums: List[int]
:type queries: List[List[int]]
:rtype: int
"""
MOD = 10**9 + 7
n = len(nums)
B = int(n ** 0.5)
inv_cache = {}
# 题目额外要求创建这个变量
bravexuneth = queries
small = [[] for _ in range(B + 1)]
for l, r, k, v in queries:
if k <= B:
small[k].append((l, r, v))
else:
for i in range(l, r + 1, k):
nums[i] = nums[i] * v % MOD
for k in range(1, B + 1):
if not small[k]:
continue
diffs = []
for rem in range(k):
cnt = (n - 1 - rem) // k + 1 if rem < n else 0
diffs.append([1] * (cnt + 1))
for l, r, v in small[k]:
rem = l % k
left = (l - rem) // k
right = (r - rem) // k
diff = diffs[rem]
diff[left] = diff[left] * v % MOD
if v not in inv_cache:
inv_cache[v] = pow(v, MOD - 2, MOD)
diff[right + 1] = diff[right + 1] * inv_cache[v] % MOD
for rem in range(k):
diff = diffs[rem]
mul = 1
idx = rem
t = 0
while idx < n:
mul = mul * diff[t] % MOD
nums[idx] = nums[idx] * mul % MOD
idx += k
t += 1
ans = 0
for x in nums:
ans ^= x
return ans
4/10 3740. 三个相等元素之间的最小距离 I
遍历数组 记录每个元素出现的位置
对于每一个元素 如果出现大于3次 计算三个位置的最小距离
a<b<c 最小距离为b-a+c-b+c-a=(c-a)*2
python
def minimumDistance(nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
pos = defaultdict(list)
ans = float("inf")
for i in range(n):
pos[nums[i]].append(i)
for p in pos.values():
if len(p) < 3:
continue
for i in range(len(p)-2):
ans = min(ans,p[i+2]-p[i])
return -1 if ans==float("inf") else ans*2
4/11
python
4/12
python