문제
https://school.programmers.co.kr/learn/courses/30/lessons/12906?language=python3
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 설명
배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,
- arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
- arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.
배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.
제한사항
- 배열 arr의 크기 : 1,000,000 이하의 자연수
- 배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수
입출력 예
arr | answer |
[1,1,3,3,0,1,1] | [1,3,0,1] |
[4,4,4,3,3] | [4,3] |
입출력 예 설명
입출력 예 #1,2
문제의 예시와 같습니다.
풀이
def solution(arr):
answer=[arr[0]]
for i in arr:
if answer[-1]!=i:
answer.append(i)
return answer
설명
arr[0]을 원소로 가지는 리스트 answer을 만든다. for문을 통해 i를 arr의 각 원소로 하여, 만약 answer의 마지막 원소(answer[-1])와 i가 다르면 answer에 i를 append해준다. 이렇게 하면 arr의 각 원소들은 arr에서 연속적으로 나타나는 값들 중 가장 앞에 있는 값만 answer에 들어가게 된다. 따라서 answer는 arr에서 연속적으로 나타나는 숫자를 제거하고 남은 수들로 이루어진 리스트가 된다. 이후 answer를 반환한다.
Tip (아래 "더보기" 클릭)
문제에서는 "배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return..." 이라고 적혀있다. 그렇다면 위 풀이에서 처럼 새로운 리스트 answer에 값을 집어넣는 방식이 아닌, arr에서 연속적으로 나타나는 수들을 제거하는 방식으로 문제를 풀면 어떨까? 가능은 하지만, 시간 복잡도 측면에서 매우 별로인 풀이가 된다.
먼저 위 풀이에서 시간 복잡도를 분석해보자.
def solution(arr):
answer=[arr[0]] # 리스트 인덱싱 O(1)
for i in arr: # arr의 각 원소에 대한 for문 O(N)
if answer[len(answer)-1]!=i: # len(리스트) O(1) * 리스트 인덱싱 O(1) * 비교 연산자 O(1)= O(1)
answer.append(i) # 리스트 append O(1)
return answer # 전체 시간 복잡도 = O(1) + O(N) * (O(1) + O(1))= O(N)
위와 같이 전체 시간 복잡도는 O(N)이 된다.
다음으로 arr에서 연속적으로 나타나는 수들을 제거하는 방식의 시간 복잡도를 살펴보자.
def solution(arr):
idx=1 # 대입 O(1)
while(len(arr)!=idx): # len(리스트) O(1) * 비교 연산자 O(1) * 반복문 O(N) = O(N)
if arr[idx-1]==arr[idx]: # 비교 연산자: O(1)
del arr[idx] # 리스트에서 값 제거 O(N)
else:
idx+=1 # 값 수정 O(1)
return arr # 전체 시간 복잡도 O(1) + O(N) * (O(N) + O(1)) = O(N^2)
위 코드는 idx라는 arr의 원소의 인덱스를 가리키는 변수를 두어 arr[idx]와 arr[idx-1]가 같을 경우 arr[idx]를 제거하는 방식이다. 이 과정을 idx와 len(arr)이 같아질 때 까지 반복하면 arr은 연속적으로 나타나는 수들이 제거된 리스트가 된다.
이 방식의 전체 시간 복잡도는 O(N^2)이다. 시간 복잡도가 이렇게 된 가장 큰 이유 중 하나는 리스트에서 값을 제거하는 함수 del의 시간 복잡도가 O(N)이기 때문이다(만약 remove()를 사용하여 푼다 해도 remove()의 시간 복잡도 역시 O(N)이다). 따라서 이 풀이로 프로그래머스에서 제출을 할 경우 아래 사진과 같이 정확성 테스트에서는 만점을 받지만, 효율성 테스트는 하나도 통과하지 못한다.

TIL
- len(리스트) → 시간 복잡도 O(1) (O(N)이 아니다!!!)
'Algorithm, 코딩테스트' 카테고리의 다른 글
3진법 뒤집기-파이썬(Python) [프로그래머스/코딩테스트 연습/Lv.1] (0) | 2022.10.12 |
---|---|
이상한 문자 만들기-파이썬(Python) [프로그래머스/코딩테스트 연습/Lv.1] (0) | 2022.10.10 |
최대공약수와 최소공배수-파이썬(Python) [프로그래머스/코딩테스트 연습/Lv.1] (0) | 2022.10.07 |
직사각형 별찍기-파이썬(Python) [프로그래머스/코딩테스트 연습/Lv.1] (0) | 2022.10.07 |
부족한 금액 계산하기-파이썬(Python) [프로그래머스/코딩테스트 연습/Lv.1] (1) | 2022.10.07 |