Programmers Coding Quiz #4 같은 숫자는 싫어

김기욱·2021년 1월 24일
0

코딩테스트

목록 보기
4/68

문제 설명

배열 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보다 작거나 같은 정수

입출력 예

arranswer
[1,1,3,3,0,1,1][1,3,0,1]
[4,4,4,3,3][4,3]

풀이

제일 처음 제가 조건에서 보았던 키워드는 두 개 였습니다.
중복제거, 순서유지 그래서 단순하게 코드를 짰었죠.

import pandas
def solution(arr):
	return pandas.unique(arr).tolist()

예전에 기업협업 프로젝트에서도 썼던 판다스 메서드입니다. 정말 간단하게 중복제거와 순서유지를 해결해주죠. 하지만 당연히 실패합니다. 판다스 유니크 메서드는 '모든 중복'을 허용하지 않기 때문입니다. 첫 번째 예시처럼 나열된 리스트는 모든 중복이 제거되어 [1,3,0]이 리턴되버리고 맙니다.

그래서 중복제거가 아닌 나열된 숫자 중에 하나만 추출해서 새롭게 리스트를 만들어내자라고 생각을 바꿉니다.

def solution(arr):
    answer = []
    for i, v in enumerate(arr):
        if i == len(arr)-1:
            answer.append(arr[i])
            break
        if arr[i] != arr[i+1]:
            answer.append(arr[i])
    return answer

우선 i가 최대인덱스값에 도달하면, i+1은 리스트 범위를 벗어난 인덱스이기 때문에 에러가 뜨게됩니다. 그러므로 최대인덱스에선 최대인덱스에 해당하는 요소를 넣어주고, for문을 break로 끝냅니다.

그리고 아래 조건문에서는 i, i+1를 비교해 같지않으면 answer라는 새로운 리스트에 넣어줍니다. 왜 첫 번째 조건문에서 마지막 인덱스를 무조건 넣냐면 다음과 같은 이유 때문입니다.

1) 마지막 두개가 다른 경우
arr = [1, 2, 3, 3, 4, 5, 5, 6]
i가 두번째 5(index = 6)에 있을 때, 6과 다르므로 5를 넣어주고 그 다음 루프에서 마지막 인덱스인 6도 넣어준다.

2) 마지막 두개가 같은 경우
arr = [1, 2, 3, 3, 4, 5, 6, 6]
i가 첫 번째 6(index = 6)에 있을 때, 6과 같으므로 넣어지지 않아지고 6까지 오게됨. 마지막 인덱스인 6을 넣어줘야 함.

그러므로 마지막 인덱스는 무조건 넣고, 루프를 끝내줘야 합니다.

다른풀이

def solution(arr):
    answer = []
    for v in arr:
        if answer[-1:] == [v]: 
            continue
        answer.append(v)
    return answer

슬라이싱을 이용한 아주 센스있는 풀이입니다.

핵심은 answer[-1:]입니다. answer[-1]과 같은 인덱싱과 다르게 슬라이싱은 빈 리스트도 에러를 반환하지 않습니다. 그리고 요소가 있다면 가장 마지막 인덱스에 해당되어있는 리스트를 뱉어냅니다.

또한 continue를 통해 중복일 경우 건너뛰고 다음 루프를 돌게되죠.
저 처럼 비교를 주어진 배열에서 앞/뒤 인덱스로 하는게 아니라 새로운 배열에 마지막 값으로 계속 비교하기 때문에 코드가 간결하고 실행 속도도 더 빠릅니다. 또 배웠습니다. 😆

def solution(arr):
    # 리스트컴프리헨션 + 슬라이싱
    return [arr[i] for i in range(len(arr)) if [arr[i]] != arr[i+1:i+2]]

슬라이싱을 이용해 구현한 한 줄 짜리 풀이입니다.
다만 새로운 배열에 슬라이싱을 하는게 아니라 주어진 배열에 슬라이싱을 계속해서 하기 때문에
시간복잡도에선 좋지않은 결과를 보여줍니다.

profile
어려운 것은 없다, 다만 아직 익숙치않을뿐이다.

0개의 댓글