[코딩 테스트 RUN] 코딩 기초 트레이닝 12일차: 리스트(배열)

코테런/코딩 기초 트레이닝(완주)
2026.02.17

⚠️ 주의!
프로그래머스에서 낸 코딩 문제에 대한 해답이 들어있습니다.
열람 시 주의해주세요.

 

 

 

이번에도 푸는 것은 문제 없이 해내었고, 좀 더 효율적으로 푸는 것에 대해서 생각해보기로 한다.

 

리스트 자르기

정수 n과 정수 3개가 담긴 리스트 slicer 그리고 정수 여러 개가 담긴 리스트 num_list가 주어집니다. slicer에 담긴 정수를 차례대로 a, b, c라고 할 때, n에 따라 다음과 같이 num_list를 슬라이싱 하려고 합니다.

n = 1 : num_list의 0번 인덱스부터 b번 인덱스까지
n = 2 : num_list의 a번 인덱스부터 마지막 인덱스까지
n = 3 : num_list의 a번 인덱스부터 b번 인덱스까지
n = 4 : num_list의 a번 인덱스부터 b번 인덱스까지 c 간격으로
올바르게 슬라이싱한 리스트를 return하도록 solution 함수를 완성해주세요.

 

문제 해설

시작점과 끝점, 그리고 단계가 n에 따라서 할당되어서 이것을 for문 등의 제어문으로 순회하면 되는 문제이다.

 

정답

class Solution {
    public int[] solution(int n, int[] slicer, int[] num_list) {
        int[] answer = {};
        int start = 0;
        int end = num_list.length - 1;
        int step = 1;
        
        int a = slicer[0], b = slicer[1], c = slicer[2];
        
        
        switch(n) {
            case 1 : 
                end = b; break;
            case 2 : 
                start = a; break;
            case 3 : 
                start = a;
                end = b;
                break;
            case 4 : 
                start = a;
                end = b;                
                step = c;
                break;
        }
        
       answer = new int[(end - start) / step + 1];
       
        for(int i = 0; i<answer.length; i++) {
            answer[i] = num_list[i * step + start];
        }
        
        
        return answer;
    }
}

 

좋아요를 가장 많이 받은 해설은 이것이다.

class Solution {
    public int[] solution(int n, int[] slicer, int[] num_list) {
        int start = n == 1 ? 0 : slicer[0];
        int end = n == 2 ? num_list.length - 1 : slicer[1];
        int step = n == 4 ? slicer[2] : 1;
        int[] answer = new int[(end - start + step) / step];
        for (int i = start, j = 0; i <= end; i += step) {
            answer[j++] = num_list[i];
        }
        return answer;
    }
}

 

start end step의 경우 n에 따라서 삼항연산자로 처리했다.(내 경우는 삼항연산자를 선호하지 않지만 이게 제일 깔끔할 것이다.)

여기서 특기할만한 것은 j또한 for문에 넣고 ++를 한다는 지점인데, 이 부분이 깔끔해보인다.

 


첫 번째로 나오는 음수

정수 리스트 num_list가 주어질 때, 첫 번째로 나오는 음수의 인덱스를 return하도록 solution 함수를 완성해주세요. 음수가 없다면 -1을 return합니다.

 

문제 해설

num_list를 순회돌면서 음수가 되는 것을 바로 return하면 된다.

 

 

정답

class Solution {
    public int solution(int[] num_list) {
        int answer = -1;
        for(int i = 0; i < num_list.length; i++) {
            if(num_list[i]<0){
                answer = i;
                break;
                }
            }
        return answer;
    }
}

 

가장 보편적인 것은 answer을 하지 말고 return하여 값을 바로 보내는 것이다(그쪽이 효율적이다).

 

 

배열 만들기 3

정수 배열 arr와 2개의 구간이 담긴 배열 intervals가 주어집니다.

intervals는 항상 [[a1, b1], [a2, b2]]의 꼴로 주어지며 각 구간은 닫힌 구간입니다. 닫힌 구간은 양 끝값과 그 사이의 값을 모두 포함하는 구간을 의미합니다.

이때 배열 arr의 첫 번째 구간에 해당하는 배열과 두 번째 구간에 해당하는 배열을 앞뒤로 붙여 새로운 배열을 만들어 return 하는 solution 함수를 완성해 주세요.

 

문제 해설

intervals의 배열이 고정되어 있음에 주의하고 answer의 길이를 정하자.

그리고 max값은 intervals의 [][1]값이고, min값은 intervals의 [][0]값이다. 이에 따라서 순회하되, 2개의 쿼리라는 것에 주의하여 answer에 값을 넣으면 된다.

 

 

정답

class Solution {
    public int[] solution(int[] arr, int[][] intervals) {
        int[] answer = {};
        int s = intervals[0][1] - intervals[0][0] + 1;
        int e = intervals[1][1] - intervals[1][0] + 1;
        
        answer = new int[(s + e)];
        
        for (int i = 0; i < intervals.length; i++) {
            int query_max = intervals[i][1];
            int query_min = intervals[i][0];
            for(int j = query_min; j <= query_max; j++){
                answer[(s * i + j - query_min)] = arr[j];
            }
            
        }
       
        return answer;
    }
}

 

맨 처음에는 for문 두개를 사용했는데, 그거보단 중첩 for문 사용이 더 좋아보여서 합쳤다.

 

좋아요가 가장 많은 건 이것이었다.

class Solution {
    public int[] solution(int[] arr, int[][] intervals) {

        int s1 = intervals[0][0], e1 = intervals[0][1], s2 = intervals[1][0], e2 = intervals[1][1], idx = 0;
        int[] answer = new int[e1 - s1 + e2 - s2 + 2];

        for (int i = s1; i <= e1; i++) {
            answer[idx++] = arr[i];
        }

        for (int i = s2; i <= e2; i++) {
            answer[idx++] = arr[i];
        }

        return answer;
    }
}

 

로직은 비슷하지만 방향성이 좀 달랐는데, 둘의 장점을 살린 코드는 이렇게 된다. 

 

class Solution {
    public int[] solution(int[] arr, int[][] intervals) {
        int totalLength = 0;
        for (int[] interval : intervals) {
            totalLength += (interval[1] - interval[0] + 1);
        }

        int[] answer = new int[totalLength];
        int idx = 0;

        for (int[] interval : intervals) {
            int start = interval[0];
            int end = interval[1];
            
            for (int i = start; i <= end; i++) {
                answer[idx++] = arr[i];
            }
        }

        return answer;
    }
}

 


2의 영역

정수 배열 arr가 주어집니다. 배열 안의 2가 모두 포함된 가장 작은 연속된 부분 배열을 return 하는 solution 함수를 완성해 주세요.

단, arr에 2가 없는 경우 [-1]을 return 합니다.

 

문제 해설

2의 값인 최소 인덱스와 최대 인덱스를 구하여 그부분을 잘라 answer에 넣는다. 나의 경우 for문으로 최소값에서 시작해 최대값까지 순회했다.

 

 

정답

class Solution {
    public int[] solution(int[] arr) {
        int[] answer = {};
        int min_two = 0, max_two = 0;
        
        for(int i = 0; i < arr.length; i++) {
            if(arr[i] == 2) {
                min_two = i;
                break;
            }
        }
        
        for(int i = 0; i < arr.length; i++) {
            if(arr[i] == 2) {
                max_two = i;
            }
        }
        
        answer = new int[max_two - min_two + 1];
        if(min_two == 0 && max_two == 0) {
           answer[0] = -1;
        } else {
        
                for(int i = min_two; i <= max_two; i++) {
                    answer[i - min_two] = arr[i];
                }
            }
        
                
        return answer;
    }
}

 

 

다만 이 경우는 치명적인 오류가 있는데 [2]만 있을 경우도 -1을 반환한다는 것이다.

모범적인 정답은 다음과 같다.

 

import java.util.*;
class Solution {
    public ArrayList<Integer> solution(int[] arr) {
        ArrayList<Integer> answer = new ArrayList<Integer>();
        int start = -1;
        int end = -1;
        for(int i = 0; i<arr.length; i++){
            if(arr[i]==2){
                start = i;
                break;
            }
        }
        for(int i = arr.length-1; i>=0; i--){
            if(arr[i]==2){
                end = i;
                break;
            }
        }
        if(start==-1 && end==-1){
            answer.add(-1);
        } else{
            for(int i = start; i<=end; i++){
                answer.add(arr[i]);
            }
        }

        return answer;
    }
}

 

이쪽은 max쪽을 뒤에서부터 순회하고, ArrayList를 사용하였다. stream을 사용한 코드도 있지만 가독성이 떨어지기 때문에 넘긴다.

 


배열 조각하기

정수 배열 arr와 query가 주어집니다.

query를 순회하면서 다음 작업을 반복합니다.

짝수 인덱스에서는 arr에서 query[i]번 인덱스를 제외하고 배열의 query[i]번 인덱스 뒷부분을 잘라서 버립니다.
홀수 인덱스에서는 arr에서 query[i]번 인덱스는 제외하고 배열의 query[i]번 인덱스 앞부분을 잘라서 버립니다.
위 작업을 마친 후 남은 arr의 부분 배열을 return 하는 solution 함수를 완성해 주세요.

 

 

문제 해설

일단 배열을 건드므로 ArrayList사용이 좋다. 홀수 및 짝수 여부와 함께 index 제거를 한다. 여기서 index와 전체 배열의 길이에도 신경쓸 것. 이 경우 뒤에서부터 세는 것이 가장 낫다.

 

정답

import java.util.ArrayList;

class Solution {
    public int[] solution(int[] arr, int[] query) {
    int query_idx = 0;
        int[] answer = {};
        
        ArrayList<Integer> list = new ArrayList<>();
        for(int idx : arr){
            list.add(idx);
        }
        
        for(int i = 0; i < query.length; i++){
            query_idx = query[i];
            
            if(i % 2 == 0) { //짝수라면
                for(int j = (list.size() - 1); j > query_idx; j--) {
                list.remove(j);
            }
            
            } else { //홀수라면
                for(int j = (query_idx - 1); j >= 0; j--) {
                list.remove(j);
                }
            }
        }
        
        answer = new int[list.size()];
        
        for(int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
        }
                    
        
        return answer;
    }
}

 

가장 많은 좋아요를 받은 답은 이것이다.

import java.util.*;

class Solution {
    public int[] solution(int[] arr, int[] query) {
        int start = 0;
        int end = arr.length - 1;
        for (int i = 0; i < query.length; i++) {
            if (i % 2 == 0) {
                end = start + query[i] - 1;
            } else {
                start += query[i];
            }
        }

        return Arrays.copyOfRange(arr, start, end + 2);
    }
}

 

처음값과 끝값만 알고 이를 Arrays.copyOfRange로 복사하여 가져간 것이다.

 

Arrays.copyOfRange(배열, 시작 인덱스, 끝 인덱스(미포함))

시작 인덱스부터 끝 인덱스 직전까지 복사한 배열을 새로 만들어 반환한다.