본문 바로가기
AI/Coding_Test

Day 13) 프로그래머스 파이썬 슬라이싱 3문제 풀이

by 거대웅 TitanBear 2026. 7. 21.

Programmers Coding Test · Day 13 · Python

파이썬 슬라이싱 3문제 풀이

n번째 위치를 파이썬 인덱스로 바꾸는 법부터, 기준점을 중심으로 리스트를 나누고 원하는 문자를 찾는 즉시 반환하는 방법까지 정리했습니다.

오늘은 슬라이싱을 이용해 리스트의 일부를 꺼내거나 앞뒤 순서를 바꾸는 문제를 풀었다. 처음 두 문제는 접근과 코드가 모두 정확했다. 세 번째 문제인 왼쪽 오른쪽에서는 슬라이싱할 대상, elsereturn의 위치, 기준 문자를 결과에서 제외하는 방법을 여러 번 고치면서 답을 완성했다.

오늘의 핵심 문제의 표현이 "n번째"인지 "n번째 이후"인지 먼저 구분해야 한다. 사람의 순서는 1부터 시작하지만 파이썬 인덱스는 0부터 시작한다. 또한 리스트에서 특정 기준을 처음 발견했을 때 답이 결정된다면 값을 계속 덮어쓰지 말고 바로 return하는 편이 명확하다.

문제 및 공식 링크

프로그래머스 코딩 기초 트레이닝 슬라이싱 문제
순서문제핵심 개념
1n 번째 원소부터1-based와 0-based 인덱스
2순서 바꾸기리스트 분할과 연결
3왼쪽 오른쪽enumerate(), 조기 반환

1. n 번째 원소부터

정수 리스트 num_list와 정수 n이 주어지면 n번째 원소부터 마지막 원소까지를 새 리스트로 반환하는 문제다.

내 풀이

def solution(num_list, n):
    answer = num_list[n - 1:]
    return answer

이 풀이는 그대로 정답이다. 문제의 n번째는 1부터 세지만 파이썬 리스트의 인덱스는 0부터 센다. 따라서 n번째 원소의 인덱스는 n - 1이다. 슬라이싱의 끝을 생략한 [n - 1:]은 그 위치부터 리스트 끝까지 가져온다.

1
사람이 세는 위치첫 번째, 두 번째, 세 번째처럼 1부터 시작한다.
2
파이썬 인덱스0, 1, 2처럼 0부터 시작하므로 n번째 위치는 n - 1이다.
3
끝점 생략num_list[n - 1:]에서 콜론 뒤를 비우면 마지막 원소까지 선택한다.

더 간단한 풀이

def solution(num_list, n):
    return num_list[n - 1:]

answer를 별도로 저장할 필요가 없다면 슬라이싱 결과를 바로 반환할 수 있다. 두 코드는 결과와 시간 복잡도가 같다. 길이가 k인 결과 리스트를 새로 만들기 때문에 시간과 추가 공간은 모두 O(k)다.

검산

n 번째 원소부터 입출력 확인
num_listn시작 인덱스결과
[2, 1, 6]32[6]
[5, 2, 1, 7, 5]21[2, 1, 7, 5]

2. 순서 바꾸기

리스트를 n번째 원소까지의 앞부분과 n번째 원소 이후의 뒷부분으로 나눈 뒤, 뒷부분을 앞에 붙이는 문제다. 이 문제에서는 n번째 원소까지가 앞부분에 포함되므로 자르는 기준이 n이다.

내 풀이

def solution(num_list, n):
    answer = []
    answer = num_list[n:] + num_list[:n]
    return answer

핵심 슬라이싱은 정확하다. num_list[n:]은 n번째 원소 이후의 뒷부분이고, num_list[:n]은 n번째 원소까지의 앞부분이다. 리스트끼리 +를 사용하면 원소별 덧셈이 아니라 두 리스트를 차례로 연결한다.

수정할 부분은 불필요한 초기화 한 줄뿐이다 처음 만든 빈 리스트 answer = []는 바로 다음 줄에서 새 리스트로 덮어쓴다. 오류는 아니지만 사용되지 않으므로 지우는 편이 낫다.

정리한 기본 풀이

def solution(num_list, n):
    back = num_list[n:]
    front = num_list[:n]
    return back + front

처음 슬라이싱을 배울 때는 backfront를 나눠 적으면 문제의 문장과 코드가 바로 연결된다. 동작을 이해한 뒤에는 아래처럼 한 줄로 줄일 수 있다.

더 간단한 풀이

def solution(num_list, n):
    return num_list[n:] + num_list[:n]
왜 n - 1이 아니라 n일까? 첫 번째 문제는 "n번째 원소부터"이므로 n번째 원소를 포함해 n - 1에서 시작했다. 이번 문제는 "n번째 원소 이후"가 뒷부분의 시작이므로 n번째 원소 바로 다음 인덱스인 n에서 자른다.

검산

순서 바꾸기 입출력 확인
입력뒷부분앞부분결과
[2, 1, 6], n=1[1, 6][2][1, 6, 2]
[5, 2, 1, 7, 5], n=3[7, 5][5, 2, 1][7, 5, 5, 2, 1]

3. 왼쪽 오른쪽

str_list를 왼쪽부터 확인해 "l""r" 중 먼저 나온 문자를 찾는다. "l"이 먼저 나오면 그 왼쪽을, "r"이 먼저 나오면 그 오른쪽을 반환한다. 두 문자가 모두 없으면 빈 리스트를 반환한다.

처음 작성한 코드

def solution(str_list):
    answer = []

    for i, str in enumerate(str_list):
        if str == "u":
            answer = [:i]
        elif str == "r":
            answer = [i:]
        else:
            answer = []

    return answer

인덱스와 현재 문자를 함께 얻기 위해 enumerate()를 선택한 방향은 좋았다. 다만 슬라이싱 문법과 반복 종료 시점에서 몇 가지 문제가 있었다.

1
비교할 문자가 다르다문제의 기준은 "l""r"이다. 첫 조건의 "u""l"로 고쳐야 한다.
2
슬라이싱 대상이 빠졌다[:i]만 쓸 수는 없다. 무엇을 자를지 앞에 적어 str_list[:i]처럼 작성해야 한다.
3
r 자체는 결과에서 제외한다str_list[i:]"r"도 포함한다. 오른쪽 원소만 가져오려면 str_list[i + 1:]이어야 한다.
4
답이 정해지면 즉시 끝낸다먼저 나온 "l" 또는 "r"만 중요하다. 발견한 결과를 저장한 뒤 반복을 계속하면 이후 값으로 덮어쓸 수 있으므로 바로 반환하는 것이 안전하다.
5
내장 함수 이름은 변수로 피한다str은 문자열 변환에 사용하는 파이썬 내장 함수다. 문법 오류는 아니지만 chardirection처럼 역할이 드러나는 이름이 좋다.

두 번째 시도

def solution(str_list):
    for i, char in enumerate(str_list):
        if char == "l":
            return char[:i]
        elif char == "r":
            return char[i:]
        else:
            return []

이번에는 답이 정해질 때 바로 return하도록 바꿨지만, 여전히 전체 리스트가 아닌 한 글자인 char를 자르고 있다. 또한 첫 원소가 "l"이나 "r"이 아니면 else에서 바로 빈 리스트를 반환하므로 뒤쪽 원소를 확인할 기회를 잃는다.

빈 리스트 반환은 반복문이 끝난 뒤에 둔다 "l""r"이 없다는 사실은 리스트 전체를 확인한 뒤에야 알 수 있다. 따라서 return []for문 밖에 있어야 한다.

최종 수정 풀이

def solution(str_list):
    for i, char in enumerate(str_list):
        if char == "l":
            return str_list[:i]
        elif char == "r":
            return str_list[i + 1:]

    return []

enumerate(str_list)는 인덱스 i와 현재 값 char를 동시에 준다. 왼쪽부터 탐색하기 때문에 처음 만난 "l" 또는 "r"이 문제에서 요구한 기준 문자가 된다. 답이 결정된 순간 반환하므로 뒤의 원소는 볼 필요가 없다.

range(len())을 사용한 내 풀이

def solution(str_list):
    for i in range(len(str_list)):
        if str_list[i] == "l":
            return str_list[:i]
        elif str_list[i] == "r":
            return str_list[i + 1:]

    return []

이 코드도 정확한 정답이다. range(len(str_list))는 인덱스를 직접 순회하고, enumerate(str_list)는 인덱스와 값을 함께 순회한다. 현재 값과 인덱스가 모두 필요한 이 문제에서는 enumerate() 쪽이 같은 표현을 반복하지 않아 조금 더 읽기 쉽다.

조건을 묶은 간단한 풀이

def solution(str_list):
    for i, direction in enumerate(str_list):
        if direction in ("l", "r"):
            return str_list[:i] if direction == "l" else str_list[i + 1:]

    return []

두 기준 문자를 한 조건에서 찾고 삼항 조건식으로 반환 범위를 선택하는 방법이다. 코드는 짧지만 슬라이싱을 처음 배우는 단계라면 ifelif를 나눈 최종 수정 풀이가 의도를 더 분명하게 보여준다.

for-else도 가능할까?

def solution(str_list):
    for i, char in enumerate(str_list):
        if char == "l":
            return str_list[:i]
        elif char == "r":
            return str_list[i + 1:]
    else:
        return []

이 형태도 동작한다. 파이썬의 for-else에서 else는 반복이 정상적으로 끝났을 때 실행된다. 이 코드에서는 기준 문자를 찾으면 함수가 먼저 반환되고, 끝까지 찾지 못했을 때만 빈 리스트를 반환한다. 다만 break를 사용하지 않는 짧은 함수에서는 for문 뒤에 return []을 두는 방식이 더 익숙하고 단순하다.

검산

왼쪽 오른쪽의 기준 문자와 결과
str_list먼저 찾은 문자결과
["u", "u", "l", "r"]"l"["u", "u"]
["l"]"l"[]
["u", "d", "r", "d"]"r"["d"]
["u", "d"]없음[]

보충: 슬라이싱과 파이썬 메모리

공부할 때 프로그램 메모리를 정적 영역, 스택, 힙으로 나누는 그림을 함께 보았다. 프로그램의 메모리 구조를 큰 틀에서 이해하는 데는 유용하지만, 파이썬 코드를 설명할 때 모든 지역 변수가 곧바로 스택에 저장되고 리스트는 힙에 저장된다고 단정하면 실제 구현을 지나치게 단순화하게 된다.

1
변수는 객체를 가리키는 이름이다num_list, i, char 같은 이름은 실행 중인 함수의 프레임에서 각각의 파이썬 객체를 참조한다.
2
리스트 슬라이싱은 새 리스트를 만든다num_list[n - 1:]은 원본과 별개의 리스트 객체를 만든다. 다만 내부 원소 자체를 깊게 복사하는 것은 아니므로 중첩 리스트에서는 같은 하위 객체를 참조할 수 있다.
3
정수와 문자열은 불변 객체다이번 문제의 정수와 한 글자 문자열은 값을 직접 바꿀 수 없는 불변 객체라서 얕은 복사로 인한 문제가 드러나지 않는다.
source = [[1], [2]]
cut = source[:1]

cut[0].append(9)

print(source)  # [[1, 9], [2]]
print(cut)     # [[1, 9]]

sourcecut은 서로 다른 바깥 리스트지만 첫 번째 내부 리스트는 함께 참조한다. 슬라이싱을 단순히 "원본 전체를 완전히 복제한다"고 이해하지 않고 새 리스트를 만드는 얕은 복사라고 기억하면 이후 중첩 리스트 문제에서 도움이 된다.

실수 방지 체크리스트

문제의 n번째를 파이썬 인덱스로 바꿀 때 n - 1이 필요한지 확인한다.
"n번째부터"와 "n번째 이후"를 구분한다.
[:i]처럼 대상을 빠뜨리지 않고 str_list[:i]처럼 작성한다.
기준 원소를 결과에 포함할지에 따라 ii + 1을 구분한다.
첫 번째 일치 항목이 답이라면 찾는 즉시 반환한다.
실패 결과는 전체 탐색이 끝난 뒤 반환한다.
str, list처럼 파이썬 내장 함수 이름을 변수명으로 사용하지 않는다.

같이 보면 좋은 자료

1
파이썬 공식 문서: 시퀀스 연산슬라이싱과 리스트 연결을 포함한 공통 시퀀스 연산을 확인할 수 있다.
2
파이썬 공식 문서: enumerate()인덱스와 값을 함께 순회하는 기본 함수의 동작을 정리한 문서다.
3
파이썬 공식 문서: 메모리 관리파이썬 메모리 관리가 일반적인 스택과 힙 그림보다 세부적으로 어떻게 설명되는지 살펴볼 수 있다.
마무리

이번 세 문제에서 가장 중요한 차이는 한 칸이었다. n - 1, n, i + 1은 모두 기준 원소를 포함할지 제외할지에 따라 달라진다. 슬라이싱을 쓰기 전에 시작 위치가 가리키는 원소와 끝 위치가 결과에 포함되는지를 작은 예로 먼저 적어 보면 실수를 크게 줄일 수 있다. 특히 세 번째 문제를 여러 번 고치며 슬라이싱의 대상과 반환 위치를 직접 찾아낸 과정이 다음 탐색 문제에도 그대로 이어질 핵심 연습이었다.