import sys
from collections import deque
input = sys.stdin.readline
dr = [-1, 0, 0, 1]
dc = [0, -1, 1, 0]
# 해당 포인트에서 가장 가까운 물고기 찾기
def bfs(r, c):
global size
visited = [[0] * n for _ in range(n)]
q = deque([(r,c)])
visited[r][c] = 1
fish = []
while q:
cr, cc = q.popleft()
# 만약 물
if fish and fish[0][0] < visited[cr][cc]:
continue
for i in range(4):
nr = cr + dr[i]
nc = cc + dc[i]
if 0 <= nr < n and 0 <= nc < n and not visited[nr][nc]:
# 일단 최단 거리 방문 처리(못 감, 갈 수 있으나 못 먹음, 갈 수 있고 먹을 수 있음)
visited[nr][nc] = visited[cr][cc] + 1
if 0 <= arr[nr][nc] <= size[0]: # 갈 수 있음
q.append((nr, nc))
if 0 < arr[nr][nc] < size[0]: # 갈 수 있고 먹을 수 있음
fish.append((visited[cr][cc], nr, nc))
return sorted(fish, key=lambda x : (x[0], x[1], x[2]))
# 물고기 먹기
def eat_fish(r, c):
global size, time
while True:
fish = bfs(r, c)
if not fish:
return time
# 위치 갱신
cnt, r, c = fish[0]
time += cnt
size[1] += 1
# 먹은 물고기 위치 0으로
arr[r][c] = 0
if size[0] == size[1]:
size[0] += 1
size[1] = 0
n = int(input())
arr = []
size = [2, 0]
time = 0
for row in range(n):
temp = list(map(int, input().split()))
if 9 in temp:
sr = row
sc = temp.index(9)
temp[sc] = 0
arr.append(temp)
print(eat_fish(sr, sc))
위 문제의 풀이 중에
sorted(fish, lambda x:(x[0],x[1],x[2]))
위와 같이 lambda를 이용하여 내부 index 순으로 요소들을 정렬하는 코드가 있다. 그러나 사실 sorted(fish)만 해도 사전순 정렬이기 때문에 결과값은 같다.
다만 내부 동작 방식은 다음과 같은 차이가 있다.
기본 비교 방식이므로 튜플 내부 요소를 자동으로 비교.
비교 연산만 수행되므로 추가적인 key 계산이 필요 없음.
시간 복잡도: O(n log n)
key= 함수를 먼저 모든 원소에 대해 한 번씩 실행하여 key 값을 따로 저장.
그 후 key 값에 대해 정렬.
파이썬 내부 동작:
key 함수 계산 → O(n)
정렬 자체 → O(n log n) (key 값을 기준으로)
총 시간 복잡도: O(n + n log n) = O(n log n)
둘 다 O(n log n)이지만
1) 기본적으로 lambda는 각 비교 전에 lambda 함수 호출 오버헤드 및
새로운 튜플 생성에 따른 메모리 할당 및 복사 작업이 있으므로 sorted()가 이론상 더 빠르다.
2) 그러나 실제 백준 채점 결과는 lambda가 살짝 더 빠르게 나왔다.
워낙 사소한 차이지만 가능한 이유는 key값 캐싱을 통한 성능 개선 및 메모리 지역성 등이 있을 수 있음. 정확한 이유는 나도 모름..아는 분 알려주세요