728x90
1. 문제

주어진 배열 arr에서 연속으로 중복되는 숫자들을 제거하고, 중복 없이 남은 숫자들을 원래의 순서대로 반환하는 문제입니다. 중요한 점은 숫자가 단순히 여러 번 나왔다고 제거하는 것이 아니라, 연속해서 중복된 경우에만 제거한다는 점입니다.
예를 들어, 같은 숫자가 반복되어도 떨어져 있으면 제거 대상이 아닙니다.
- [1,1,3,3,0,1,1] → [1,3,0,1]
- [4,4,4,3,3] → [4,3]
🔒 제한사항 요약
- 배열 arr의 길이: 1 이상 1,000,000 이하
- 배열의 각 원소는: 0 이상 9 이하의 정수
- 출력 배열도 입력 순서를 그대로 유지해야 함
- 시간 효율을 고려해야 함 (입력이 최대 백만 개)
2. 풀이 코드
import java.util.ArrayList;
import java.util.List;
public class Solution04 {
public int[] solution(int []arr) {
List<Integer> list = new ArrayList<>();
for(int i=0; i<arr.length; i++) {
if(i==0 || arr[i] != arr[i-1]){
list.add(arr[i]);
}
}
int answer[] = new int[list.size()];
for(int i=0; i<list.size(); i++) {
answer[i] = list.get(i);
}
return answer;
// int[] answer = {};
// for(int i=0; i<arr.length; i++) {
// // 배열의 길이가 1인 경우
// if(arr.length == 1) {
// answer = new int[]{arr[0]};
// return answer;
// }
// // 배열의 길이가 2 이상인 경우
// if(i == 0) {
// // 첫 번째 요소는 무조건 추가
// answer = new int[]{arr[i]};
// } else {
// // 이전 요소와 비교하여 중복되지 않는 경우에만 추가
// if(arr[i] != arr[i-1]) {
// answer = Arrays.copyOf(answer, answer.length + 1);
// answer[answer.length - 1] = arr[i];
// }
// }
// }
// // [실행] 버튼을 누르면 출력 값을 볼 수 있습니다.
// System.out.println("Hello Java");
// return answer;
}
}
3. 코드 풀이
List<Integer> list = new ArrayList<>();
- 중복을 제거한 결과를 임시로 저장할 리스트입니다.
- ArrayList는 크기가 가변적인 동적 배열로, 값을 자유롭게 추가할 수 있습니다.
for(int i=0; i<arr.length; i++) {
if(i==0 || arr[i] != arr[i-1]){
list.add(arr[i]);
}
}
- 배열 arr을 처음부터 끝까지 순회합니다.
- i == 0이면 무조건 추가합니다. (첫 요소는 이전 요소가 없기 때문)
- 이후부터는 현재 값이 이전 값과 다를 때만 리스트에 추가합니다.
- 즉, 연속된 숫자 중 첫 번째만 저장합니다.
- 예: [1, 1, 3] → 1은 한 번만, 3은 새로 등장하므로 추가
int answer[] = new int[list.size()];
for(int i=0; i<list.size(); i++) {
answer[i] = list.get(i);
}
- list에 담긴 결과를 int 배열로 변환합니다.
- ArrayList는 기본형 배열로 바로 변환할 수 없기 때문에, 수동으로 복사합니다.
- 이 과정을 거쳐 최종 answer 배열에 결과값이 담깁니다.
4. 이 코드에서 나온 개념 정리
1) ArrayList 정의
- Java에서 제공하는 가변 길이 배열 클래스
- 배열(int[])은 크기가 고정이지만, ArrayList는 자동으로 크기가 늘어남
- 내부적으로는 배열 기반이므로 접근 속도가 빠름
- 데이터 추가/삭제가 많을 때 LinkedList보다 빠름
2) 선언 방법
import java.util.ArrayList;
import java.util.List;
// 기본형은 wrapper 클래스 사용 (int → Integer)
List<Integer> list = new ArrayList<>();
3) 자주 사용되는 메서드들
| 메서드 | 설명 | 예시 |
| add(E e) | 맨 뒤에 요소 추가 | list.add(10) |
| add(int index, E e) | 특정 위치에 요소 삽입 | list.add(1, 20) |
| get(int index) | 인덱스 위치의 요소 반환 | list.get(0) → 10 |
| set(int index, E e) | 인덱스 위치 값을 수정 | list.set(0, 99) |
| remove(int index) | 인덱스 위치 요소 삭제 | list.remove(0) |
| remove(Object o) | 특정 값을 찾아 삭제 | list.remove(Integer.valueOf(3)) |
| size() | 리스트의 현재 크기 반환 | list.size() |
| isEmpty() | 리스트가 비었는지 확인 | list.isEmpty() |
| clear() | 모든 요소 제거 | list.clear() |
| contains(Object o) | 특정 요소 포함 여부 | list.contains(5) |
| indexOf(Object o) | 특정 요소의 첫 인덱스 반환 | list.indexOf(3) |
| toArray() | 리스트 → 배열 변환 | list.toArray(new Integer[0]) |
| stream() | 스트림 처리 시작 | list.stream().map(...) |
4) ArrayList 관련해서 자주하는 실수
| 상황 | 주의사항 |
| 기본형 사용 | int는 안 되고 Integer 사용해야 함 |
| remove(index) vs remove(Object) | list.remove(1)과 list.remove(Integer.valueOf(1))은 다름 |
| 크기 초과 접근 | get(i) 사용 시 IndexOutOfBoundsException 주의 |
| 성능 비교 | ArrayList는 삽입/삭제보다 조회에 강점 |
5) 예시 코드
List<Integer> list = new ArrayList<>();
list.add(1); // [1]
list.add(3); // [1, 3]
list.add(1, 2); // [1, 2, 3]
list.set(0, 9); // [9, 2, 3]
list.remove(Integer.valueOf(2)); // [9, 3]
System.out.println(list.contains(3)); // true
System.out.println(list.size()); // 2
5) Array vs ArrayList 비교 정리
| 항목 | Array 배열 | ArrayList |
| 크기 | 고정 (생성 시 정해짐) | 가변 (자동으로 늘어남) |
| 자료형 | 기본형(int, double) 사용 가능 | 기본형은 Wrapper 클래스(Integer, Double)로 사용 |
| 선언 예시 | int[] arr = new int[5]; | List<Integer> list = new ArrayList<>(); |
| 추가/삭제 | 직접 구현해야 함 (System.arraycopy) | add(), remove() 등 메서드 제공 |
| 속도 | 조회 속도 빠름 (O(1)) | 조회는 빠름, 삽입/삭제는 상대적으로 느림 |
| 편의성 | 반복문 외에는 조작 불편 | 다양한 메서드로 조작이 간편 |
| 변환 | 기본형 배열 → List 변환 번거로움 | list.toArray()로 배열로 쉽게 변환 가능 |
| Null 허용 | 기본형은 불가 (int 등) | 객체라서 null 값 저장 가능 |
| 제공 메서드 | 없음 (length만 존재) | size(), contains(), clear() 등 풍부 |
| 사용처 | 고정 크기, 성능 중요할 때 | 유동 크기, 일반적인 리스트 처리 시 |
5. 다른 사람들의 코드
import java.util.*;
public class Solution {
public int[] solution(int []arr) {
ArrayList<Integer> tempList = new ArrayList<Integer>();
int preNum = 10;
for(int num : arr) {
if(preNum != num)
tempList.add(num);
preNum = num;
}
int[] answer = new int[tempList.size()];
for(int i=0; i<answer.length; i++) {
answer[i] = tempList.get(i).intValue();
}
return answer;
}
}
✅ 이 코드의 장점
| 항목 | 설명 |
| 간결한 로직 처리 | preNum 변수 하나로 이전 숫자와 비교해 중복 제거 |
| 불필요한 조건 제거 | i==0 조건 없이도 첫 원소 포함 처리가 자연스럽게 가능 |
| 향상된 for문 사용 | for (int num : arr) 형태로 코드 가독성이 향상됨 |
| 초기값 전략이 적절 | preNum = 10 설정으로 0~9 범위와 충돌 없이 첫 원소 정상 처리 |
| 불필요한 반복 제거 | arr[i] != arr[i-1]처럼 인덱스 접근을 하지 않아 오류 가능성 ↓ |
🔍 이 코드로 부터 배울 수 있는 개념
| 개념 | 설명 | 예시 |
| 향상된 for문 (for-each) | 배열이나 리스트를 순회할 때 인덱스를 직접 사용하지 않고, 요소만 꺼내 사용할 수 있는 반복문 | for (int num : arr) |
| 이전 값 저장 기법 | 반복문에서 이전 값을 변수에 저장해 두고 현재 값과 비교하는 로직 → 중복 여부 판별 등에 자주 사용됨 | int preNum = 10; → if (preNum != num) |
| 초기값 트릭 | 입력 값의 범위(0~9)를 벗어나는 값을 초기값으로 설정해 비교 조건을 자연스럽게 처리 | preNum = 10 |
| ArrayList 사용 | 크기를 모르는 결과를 임시로 저장할 때 유용한 동적 배열 | ArrayList<Integer> tempList = new ArrayList<>(); |
| ArrayList → 배열 변환 | 리스트에 데이터를 저장한 후, 고정된 배열로 반환하는 일반적인 패턴 | tempList.get(i)로 배열에 옮김 |
| 오토 언박싱 | Integer 객체를 int로 자동 변환해주는 자바 기능. .intValue()를 생략할 수 있음 | answer[i] = tempList.get(i); |
| 불변 배열 선언 | 반환용 배열은 new int[list.size()]으로 크기를 명확히 선언 후 값 복사 | int[] answer = new int[tempList.size()]; |
📌 원래 코드와 비교 요약
| 항목 | 내 코드 | 다른 사람 코드 |
| 중복 제거 방식 | arr[i] != arr[i - 1]로 비교 (인덱스 활용) | preNum 변수 사용 (가독성 좋음) |
| 초기값 처리 | i == 0 조건으로 첫 값 처리 | preNum = 10처럼 입력값 범위 밖의 초기값 사용 |
| 자료구조 | List<Integer> list = new ArrayList<>() | ArrayList<Integer> tempList = new ArrayList<>() |
| 배열로 변환 | list.get(i)로 배열에 복사 | 동일, 하지만 .intValue() 사용 |
| 반복문 스타일 | 전통적인 for (int i = 0; i < arr.length; i++) | 향상된 for-each 문 (for (int num : arr)) |
| 코드 길이/가독성 | 다소 명시적, 초보자에게 친절함 | 간결하고 직관적, 고수 느낌 |
| 확장성/유연성 | 조건 추가 시 분기문 필요 | 흐름이 더 단순하여 유지보수 용이 |
💡 누가 더 잘했는가?
| 항목 | 평가 |
| 가독성 | ✅ 다른 사람 코드 우세 → preNum + for-each 조합이 직관적 |
| 처리 정확도 | ✅ 둘 다 정확함 |
| 초기값 처리 센스 | ✅ 다른 사람 코드가 더 스마트함 (preNum = 10) |
| 학습용 코드로는? | ✅ 내 코드도 좋음 (조건 분기, 인덱스 활용 이해에 유리) |
728x90
'[JAVA] 프로그래머스 LEVEL1' 카테고리의 다른 글
| [JAVA] 두 정수 사이의 합 - 반복문, 등차수열 (2) | 2025.06.04 |
|---|---|
| [JAVA] 나누어 떨어지는 숫자 배열 - ArrayList, 배열, 람다식 (0) | 2025.06.04 |
| [JAVA] 가운데 글자 가져오기 - 문자열 인덱스 총 정리 (2) | 2025.06.04 |
| [JAVA] 2016년 - Array 배열, %연산자 (0) | 2025.06.03 |
| [JAVA] 폰켓몬 - 삼항연산자, 이중 for문, HashSet (0) | 2025.06.03 |