Cho danh sách walks biểu thị các bước di chuyển trên đường thẳng 1 chiều (bắt đầu từ vị trí 0). Giá trị dương = đi phải, âm = đi trái. Mỗi bước di chuyển 1 đơn vị (block). Cần tìm số block được đi qua ít nhất target lần.
Ví dụ
walks = [3, -7, 2], target = 2 → Output: 5
Các block được đi qua 2 lần: [0,1], [1,2], [2,3], [-4,-3], [-3,-2].
Thuật toán (Line Sweep / Difference Array)
- Dùng Difference Array (jumps) để đánh dấu bắt đầu/kết thúc đoạn đi.
- Duyệt
walks: tại vị trí hiện tạipos, tăng +1 (đi phải) hoặc -1 (đi trái); tạipos + distgiảm tương ứng. - Sắp xếp các key của jumps, duyệt tính prefix sum (
level) - số lần đi qua. - Khi
level >= target, cộng độ dài đoạn vàototal.
Code Python
from collections import defaultdict
def solve(walks, target):
pos = 0
jumps = defaultdict(int)
# Xây dựng difference array
for dist in walks:
if dist > 0:
jumps[pos] += 1
jumps[pos + dist] -= 1
else:
jumps[pos] -= 1
jumps[pos + dist] += 1
pos += dist
# Line sweep
lastpos = level = total = 0
for pos, val in sorted(jumps.items()):
if level >= target:
total += pos - lastpos
level += val
lastpos = pos
return total
# Test
walks = [3, -7, 2]
target = 2
print(solve(walks, target)) # 5
Giải thích chi tiết
Bước 1: Xây dựng jumps
walks = [3, -7, 2]
pos=0: dist=3 -> jumps[0]+=1, jumps[3]-=1 pos=3
pos=3: dist=-7 -> jumps[3]-=1, jumps[-4]+=1 pos=-4
pos=-4: dist=2 -> jumps[-4]+=1, jumps[-2]-=1 pos=-2
jumps = {0:1, 3:0, -4:2, -2:-1} # sau khi gộp
Bước 2: Line sweep (sorted keys: -4, -2, 0, 3)
pos=-4, val=2: level=0<2 -> level=2, lastpos=-4 pos=-2, val=-1: level=2>=2 -> total+=2, level=1, lastpos=-2 pos=0, val=1: level=1<2 -> level=2, lastpos=0 pos=3, val=0: level=2>=2 -> total+=3, level=2, lastpos=3 total = 2 + 3 = 5
Độ phức tạp
- Thời gian:
O(n log n)do sort (n = len(walks)). - Không gian:
O(n)cho dictionary jumps.