이 문제는 어려운 문제가 아니다. 굉장히 쉬운 문제다. 그냥 지문 그대로 옮겨서 구현만 하면 되는 문제다.
그런데 문제를 풀어낸 솔루션에서 굉장히 재미난 동작을 발견했다. 파이썬 언어차원에서의 동작인것 같은데 처음에는 왜 이렇게 동작하나 의아했는데 꽤나 재밌다는 생각이 들어서 따로 뽑아서 블로그에 정리하고자 한다. 우선 문제 링크는 아래와 같다. 슥 봐도 쉬운 문제임을 알 수 있을 것이다.
https://leetcode.com/problems/n-repeated-element-in-size-2n-array/
그런데 중요한건 문제를 어떻게 풀었냐가 아니다. 문제를 풀어낸 과정에서의 코드 몇줄에서 발생한 신기한 동작이다.
내 솔루션은 아래와 같다.
from collections import defaultdict
class Solution:
def repeatedNTimes(self, nums: List[int]) -> int:
# 길이는 2의 배수
# n + 1개의 unique 한 요소 가지고 있음.
# 정확히 한개의 요소만 n번 반복해서 등장함.
n = len(nums)//2
d = defaultdict(int)
for num in nums:
d[num] += 1
for k, v in d.items():
if v == n:
return k
자 평범한 솔루션이다. 여기서 뭐가 이상하다는 걸까? 코드를 보면 for문에서 nums에서 num을 하나씩 뽑으면서 d[num]으로 1씩 증가시켜주는 코드가 중간에 보일 것이다. 과연 여기서 반복변수로 num 이 아니라 n 을 쓴다면 어떤 동작이 발생할까?
즉 아래처럼 말이다.
from collections import defaultdict
class Solution:
def repeatedNTimes(self, nums: List[int]) -> int:
# 길이는 2의 배수
# n + 1개의 unique 한 요소 가지고 있음.
# 정확히 한개의 요소만 n번 반복해서 등장함.
n = len(nums)//2
d = defaultdict(int)
for n in nums:
d[n] += 1
for k, v in d.items():
if v == n:
return k
당연히 문제없이 동작할 것이라고 생각했다. 왜냐면 for문에서 반복변수로 사용하는 n은 for문 스코프 밖의 영역에는 영향을 주지 않을 것이라고 생각했기 때문이다. 그러나 위 코드는 오답으로 처리된다. 그것도 None을 리턴한다. 왜 이런 동작이 발생하는 걸까 추측해보았다. 왜 이럴까? 나름의 추측을 해보았다.
아마 for문 위에서 선언한 n = len(nums)//2 에서 n 변수가 할당된 location 을 아래 코드의 for문에서 반복 변수 n이 쓰이면서 해당 location을 덮어씌우는 동작을 하는 것 같다.
물론 해결 방법은 존재한다. 임시방책이긴 하지만,
n = len(nums)// 2 <- 이 코드를 for 문보다 아래에 적어주면 될 것이다.
더 확실하게 하고 싶다면? 그냥 for문이라고 해도 위에 선언된 변수와 네이밍이 겹치는 변수를 for의 반복변수로 설정하지 않으면 된다.
그런데 이런 동작은 왠지 처음 보는 것 같다. 자바나 C에서 이런 동작이 없었던것 같은데 파이썬에서는 for문에서의 반복 변수가 for 스코프 밖 변수의 메모리 셀을 건드리는 것 같다. 즉 우선적으로 스코프를 추적해서 변수를 잡는게 아니라 실제 변수 네이밍을 추적해서 변수를 잡는게 스코프보다 우선되는 것 같다. 물론 함수인 경우에는 제외인것 같다. 아마 내부적으로 다른 언어들과 미세한 동작 차이가 있는듯하다.
오랜만에 심심했는데 꽤나 재미난 동작을 보게 되어서 좋았다.
'Algorithm > 문제풀이' 카테고리의 다른 글
[LeetCode] LeetCoe 1337. The K Weakest Rows in a Matrix - python3 (0) | 2022.06.26 |
---|---|
[LeetCode] LeetCode 1037. Valid Boomerang 솔루션 - python (0) | 2022.06.18 |
[Leetcode] Leetcode 696 - count binary substring - python3 (0) | 2022.05.27 |
[BOJ] 백준 11060 점프점프 - 파이썬 (0) | 2022.03.25 |
[BOJ] 백준 16173 점프왕 쨀리 - 파이썬 (0) | 2021.08.13 |