Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 target 횟수 이상 지나간 블록 개수 계산하는 프로그램

이 문제에서는 walkstarget이라는 두 개의 리스트(값)가 주어집니다. 우리는 1차원 수직선 위의 위치 0에서 출발합니다. |walks[i]|는 실제로 걸은 걸음 수를 의미하며, walks[i]가 양수면 오른쪽으로, 음수면 왼쪽으로 이동했음을 나타냅니다. 걸을 때마다 한 블록씩 움직이므로, 현재 위치의 다음 정수 위치 또는 이전 정수 위치로 이동하게 됩니다.

우리가 구해야 하는 것은 최소 target번 이상 밟고 지나간 블록의 개수입니다.

예를 들어, 입력이 walks = [3, -7, 2]이고 target = 2라고 가정해 보겠습니다. 이 경우 출력은 5가 됩니다. 아래 그림에서 볼 수 있듯이 [0, 1], [1, 2], [2, 3], [-4, -3], [-3, -2] 구간이 각각 k = 2번 커버되기 때문입니다.

파이썬으로 target 횟수 이상 지나간 블록 개수 계산하는 프로그램

문제 해결 접근 방법

이 문제는 스위핑(sweeping) 기법을 활용해 효율적으로 해결할 수 있습니다. 각 구간의 시작점과 끝점에 변화량을 기록한 뒤, 위치 순서대로 누적하여 특정 레벨 이상 유지된 구간의 길이를 합산하는 방식입니다.

알고리즘 단계

  • 현재 위치 pos := 0으로 초기화합니다.
  • jumps라는 해시 맵(defaultdict)을 만들어, 키가 없을 때 기본값은 0이 되도록 합니다.
  • walks의 각 dist에 대해 다음을 반복합니다:
    • jumps[pos]에 dist > 0이면 +1, 아니면 -1을 더합니다.
    • jumps[pos + dist]에 dist > 0이면 -1, 아니면 +1을 더합니다.
    • pos := pos + dist로 현재 위치를 갱신합니다.
  • lastpos := 0, level := 0, total := 0으로 초기화합니다.
  • jumps의 키-값 쌍을 위치 기준으로 정렬하여 순회하면서:
    • level >= target이면 total에 (pos - lastpos)를 더합니다.
    • level에 val을 더하고, lastpos를 pos로 갱신합니다.
  • total을 반환합니다.

예제 코드

아래 파이썬 구현을 통해 동작 방식을 더 잘 이해할 수 있습니다.

from collections import defaultdict
def solve(walks, target):
    pos = 0
    jumps = defaultdict(int)
    for dist in walks:
        jumps[pos] += 1 if dist > 0 else -1
        jumps[pos + dist] -= 1 if dist > 0 else -1
        pos += dist
    lastpos = level = total = 0
    for pos, val in sorted(jumps.items()):
        if level >= target:
            total += pos - lastpos
        level += val
        lastpos = pos
    return total

walks = [3, -7, 2]
target = 2
print(solve(walks, target))

입력

[3, -7, 2], 2

출력

5

동작 원리 설명

이 알고리즘의 핵심은 각 걸음 구간을 시작점에서 +1, 끝점에서 -1로 표시하는 것입니다. 모든 지점을 정렬한 후 순차적으로 스캔하면, 어느 위치에서 몇 겹의 구간이 겹치는지(level)를 추적할 수 있습니다. level이 target 이상인 동안 이동한 거리를 모두 더하면, 정확히 target번 이상 밟힌 블록의 총 개수를 구할 수 있습니다.

이 방식은 각 걸음을 블록 단위로 하나하나 시뮬레이션하는 O(N×M) 방식보다 훨씬 효율적이며, 걸음 수가 많거나 이동 거리가 긴 경우에도 빠르게 동작합니다.