배열 문제를 풀다 보면 중복을 제거하라는 문제는 자주 나옵니다.
그런데 이때 단순히 중복만 없애는 것이 아니라, 처음 등장한 순서를 그대로 유지하라는 조건이 붙으면 생각보다 헷갈릴 수 있습니다.
이번 글에서는 정수 배열에서 중복된 값을 제거하되, 원래 등장한 순서를 유지하는 문제를 정리해보겠습니다.
이 문제는 어렵지는 않지만, 배열 순회와 Set을 함께 쓰는 연습을 하기에 좋습니다.
문제
정수 배열 nums가 주어집니다.
이 배열에서 중복된 숫자는 제거하되, 처음 등장한 순서는 그대로 유지한 새 배열을 반환하는 함수를 작성해보겠습니다.
즉, 어떤 숫자가 여러 번 나오더라도 가장 처음 나온 한 번만 결과에 남기면 됩니다.
함수 형식은 아래와 같습니다.
remove_duplicates_keep_order(nums)
nums: 정수 배열- 반환값: 중복을 제거한 새 배열
예시 1
입력: [4, 2, 4, 3, 2, 1]
출력: [4, 2, 3, 1]
설명:
- 첫 번째
4는 남깁니다 - 첫 번째
2도 남깁니다 - 뒤에 다시 나온
4,2는 이미 본 숫자이므로 제거합니다 3,1은 처음 등장했으므로 결과에 추가합니다
예시 2
입력: [7, 7, 7, 7]
출력: [7]
설명:
- 같은 숫자가 반복되므로 첫 번째
7만 남깁니다
예시 3
입력: [1, 3, 5, 7]
출력: [1, 3, 5, 7]
설명:
- 중복이 없으므로 그대로 반환합니다
처음 떠오르는 생각
이 문제의 핵심은 두 가지입니다.
- 중복인지 확인해야 합니다
- 순서는 그대로 유지해야 합니다
여기서 많이 하는 실수가 정렬해서 중복을 제거하려는 것입니다.
예를 들어:
[4, 2, 4, 3, 2, 1]
이 배열을 정렬하면:
[1, 2, 2, 3, 4, 4]
이렇게 되어버립니다.
그러면 원래의 순서인 [4, 2, 3, 1]을 만들 수 없습니다.
즉, 이 문제는 정렬하면 안 되고, 앞에서부터 순서대로 보면서 처리해야 합니다.
핵심 아이디어
이 문제는 숫자를 하나씩 보면서 이미 본 숫자인지 빠르게 확인하면 됩니다.
이럴 때 Set이 잘 맞습니다.
- 처음 보는 숫자면
Set에 넣고 결과 배열에도 추가합니다 - 이미 본 숫자면 그냥 건너뜁니다
예를 들어 [4, 2, 4, 3, 2, 1]을 보면:
초기 상태는 아래와 같습니다.
seen = {}
result = []
이제 왼쪽부터 하나씩 확인합니다.
4→ 처음 봄 →seen에 추가,result에 추가2→ 처음 봄 → 추가4→ 이미 봄 → 건너뜀3→ 처음 봄 → 추가2→ 이미 봄 → 건너뜀1→ 처음 봄 → 추가
최종 결과는 아래와 같습니다.
[4, 2, 3, 1]
코드
def remove_duplicates_keep_order(nums):
seen = set()
result = []
for num in nums:
if num not in seen:
seen.add(num)
result.append(num)
return result
코드 해설
1) 이미 본 숫자를 저장할 공간 만들기
seen = set()
seen에는 지금까지 등장한 숫자를 저장합니다.
2) 결과 배열 만들기
result = []
중복이 제거된 최종 결과를 담을 리스트입니다.
3) 배열을 앞에서부터 확인하기
for num in nums:
순서를 유지해야 하므로 반드시 앞에서부터 차례대로 확인해야 합니다.
4) 처음 보는 숫자만 결과에 넣기
if num not in seen:
seen.add(num)
result.append(num)
이 부분이 핵심입니다.
seen에 없으면 처음 보는 숫자입니다- 그러면
seen에 기록하고 result에도 추가합니다
이미 본 숫자라면 아무것도 하지 않고 넘어갑니다.
실행 예시
입력:
[4, 2, 4, 3, 2, 1]
초기 상태:
seen = {}
result = []
4
- 처음 봄
seen = {4}result = [4]
2
- 처음 봄
seen = {4, 2}result = [4, 2]
4
- 이미 봄
- 그대로 넘어감
3
- 처음 봄
seen = {4, 2, 3}result = [4, 2, 3]
2
- 이미 봄
- 그대로 넘어감
1
- 처음 봄
seen = {4, 2, 3, 1}result = [4, 2, 3, 1]
최종 결과는 아래와 같습니다.
[4, 2, 3, 1]
복잡도
배열 길이를 N이라고 하면:
- 시간 복잡도:
O(N) - 공간 복잡도:
O(N)
배열을 한 번만 순회하므로 시간은 O(N)입니다.
정리
이 문제는 단순 중복 제거와는 조금 다릅니다.
핵심은 순서를 유지해야 한다는 점입니다.
즉:
- 정렬해서 풀면 안 됩니다
- 앞에서부터 순회해야 합니다
- 이미 본 값만 빠르게 체크하면 됩니다
이 문제의 핵심은 한 줄입니다.
배열을 앞에서부터 보면서, 처음 본 숫자만 결과에 추가합니다.
즉:
- 순서대로 확인하고
- 본 적 있는지 저장하고
- 처음 나온 값만 남깁니다
이 흐름만 이해하면 쉽게 풀 수 있습니다.
이 글의 문제 상황과 예시는 학습용으로 직접 재구성한 내용입니다.