该题解采用了线段树(ZKW线段树的非递归版本)来求解问题。首先,为了应对题目中允许的跳跃范围 [-target, target],题解将数组中的每个元素 x 扩展到三个可能的跳跃值 x-target, x, x+target,并去重排序。这种扩展允许在 O(log n) 时间内查询和更新任何区间的最大值。通过映射每个扩展值到其索引,可以用线段树高效查询和更新最大的跳跃次数。遍历 nums 数组,对于每个元素 x,查询在 [x-target, x+target] 范围内的最大跳跃次数,并在线段树中更新当前 x 的位置。最后,检查是否能到达 n-1 索引处,并返回相应的跳跃次数。如果不能到达,则返回 -1。
时间复杂度: O(n log n)
空间复杂度: O(n)
inf = 1<<60
class ZKW:
\"\"\"自低向上非递归写法线段树,0_indexed
tmx = ZKW(pre, max, -2 ** 61)
\"\"\"
__slots__ = ('n', 'op', 'e', 'log', 'size', 'd')
def __init__(self, n, OP, E):
\"\"\"初始化线段树
OP: 操作:max,min,sum
E: 每个元素默认值
\"\"\"
self.n = n
self.op = OP
self.e = E
self.log = (self.n - 1).bit_length()
self.size = 1 << self.log
self.d = [E for i in range(2 * self.size)]
def build(self, V):
for i in range(self.n):
self.d[self.size+i]=V[i]
for i in range(self.size-1,0,-1):
self.update(i)
def set(self, p, x):
update = self.update
p += self.size
self.d[p] = x
for i in range(1, self.log + 1):
update(p >> i)
def get(self,p):
p+=self.size
return self.d[p]
def query(self, l, r): # [l,r] 双闭区间
sml, smr, op, d = self.e, self.e, self.op, self.d
l += self.size
r += self.size+1
while l < r:
if l & 1:
sml = op(sml, d[l])
l += 1
if r & 1:
smr = op(d[r - 1], smr)
r -= 1
l >>= 1
r >>= 1
return self.op(sml, smr)
def update(self, k):
self.d[k] = self.op(self.d[2 * k], self.d[2 * k + 1])
def all_query(self):
return self.d[1]
class Solution:
def maximumJumps(self, nums: List[int], target: int) -> int:
arr=[]
for i in nums:
arr+=[i-target,i,i+target]
arr=sorted(set(arr))
d={x:i for i,x in enumerate(arr)}
seg=ZKW(len(d),max,-inf)
seg.set(d[nums[0]],0)
n=len(nums)
for i in range(1,n):
x=nums[i]
q=seg.query(d[x-target],d[x+target])
seg.set(d[x],q+1)
if i==n-1:
if q<0:
return -1
else:
return q+1