본문 바로가기
[JAVA] 프로그래머스 LEVEL1

[JAVA] 같은 숫자는 싫어 - ArrayList, List 관련 메서드 정리

by devjapan 2025. 6. 4.
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