강의로 돌아가기
이성원

코드 피드백 부탁드립니다!!

def solution(L, x):

answer = []

for pos in range(len(L)):
answer.append(L[pos])
if x < L[pos]:
answer.insert(pos, x)
return answer
L = [1,2,4,7,8,13,17,56,66,89,99]

이렇게 실행하면
[1, 2, 4, 7, 8, 13, 17, 18, 18, 18, 18, 56, 66, 89, 99] 가 나옵니다. 왜 이렇게 나오는지는 알겠는데
x 값을 리스트에 추가하고 x 값보다 큰 수들을 어떻게 다시 리스트에 추가 하는지 아무리 생각해봐도 모르겠어요..

작성중인 코드―solution.py
1
2
3
4
5
6
7
8
9
def solution(L, x):
    answer = []
    for pos in range(len(L)):
        answer.append(L[pos])
        if x < L[pos]:
            answer.insert(pos, x)
        else:
            continue
    return answer
2 개의 답변
이시윤

위에 적은 코드는, 문제에서 의도한 기능을 올바르게 수행하지는 못합니다.

예를 들어 (문제 지문에 포함된 것이자, 실행 누르면 테스트되는 케이스), L = [20, 37, 58, 72, 91] 이고 삽입하려는 원소 x = 65 인 경우를 생각해봅시다.

처음에는 answer = [] 로 초기화됩니다 (L2). 그 후, pos = 0 에서 시작합니다. L4 에 의하여 answer.append(L[pos]), 즉 answer.append(L[0]), 즉 answer.append(20) 이 실행되므로, 그 직후 answer == [20] 입니다.

그 직후에, L5 if 의 조건은 False 입니다. x == 65 이며 pos == 0 이고, 따라서 L[pos] == L[0] == 20 이기 때문입니다 (65 < 20 == False). 그러므로 순환문의 다음 반복 회차로 넘어갑니다 (참고: else: continue 는 아무 일도 하지 않으므로 필요 없겠습니다).

이제는 pos == 1 입니다. 이것은 L3 의 for 순환문 구문에 의한 것입니다. 위와 마찬가지 과정을 반복하고, 이제는 answer == [20, 37] 입니다. 또 위 과정이 반복됩니다 (65 < 37 == False). 이 반복을 answer == [20, 37, 58] 일 때까지 (즉 pos == 2 인 경우까지) 합니다.

다음 반복에서는 pos == 3 입니다. 위와 마찬가지로, L4 가 실행한 후 answer == [20, 37, 58, 72] 입니다. 그 후 L5 if 의 조건은 참입니다 (x == 65 < L[pos] == L[3] == 72). 그러므로 L6 의 문장이 실행하는데, 이 때 pos == 3, x == 65 이므로 answer.insert(pos, x)answer.insert(3, 65) 여서, 그 결과 answer == [20, 37, 58, 65, 72] 가 됩니다. 즉, 리스트에 대한 insert(n, x) 메서드의 호출은, 인덱스 n 보다 하나 앞에 원소 x 를 끼워 넣습니다.

이제 다음 번 반복으로 넘어와, pos == 4 이고, L[pos] == L[4] == 91 입니다. 위와 마찬가지 과정을 거쳐, answer == [20, 37, 58, 65, 72, 91] 이 되고 (append() 에 의하여) L5 if 의 조건이 참이어서 answer.insert(pos, x)answer.insert(4, 65) 이므로 그것이 실행된 후 answer = [20, 37, 58, 65, 65, 72, 91] 입니다. (인덱스 4 보다 앞에 65 를 또 끼워 넣었습니다.)

이제는 pos 가 L3 에 의하여 반복할 범위를 모두 반복하였으므로 (len(L) == 5 이니까) 순환문이 종료하고 L9 에 의하여 answer 가 리턴됩니다. 올바른 결과 값은 리스트 [20, 37, 58, 65, 72, 91] 인데 이와 같지 않은 (한 번 더 삽입된) 리스트가 리턴되어 테스트는 실패합니다.

위 질문에 적은 예에서는 L.insert(18) 을 호출한 결과로 보입니다. 리스트 L 내에 18 보다 큰 원소가 네 개 있어서 (56, 66, 89, 99) 의도한 바와는 달리 18 이 네 번 삽입되었습니다.

그렇다면, 한 번만 삽입하도록 하면 의도된 기능을 제대로 행할 수 있을 것입니다. 그렇게 하는 방법에는 매우 여러 가지 접근법이 있겠지만, 위 설명에서 힌트를 얻자면, 리스트 L 의 원소를 하나 하나 검사하다가, x 보다 크거나 같은 원소가 발견되면 그 자리에 x 를 삽입하고 순환문을 빠져 나오는 방법이 있겠습니다. 리스트에 대한 insert() 메서드가 리스트 자체를 변화시킨다는 점을 이용하는 것입니다 (하나씩 꺼내서 answer 에 추가하지 않고 말이죠).

물론, 위에 예시한 코드처럼 answer 에 하나 하나 쌓아 나가는 방법도 적용할 수 있습니다. 이러한 경우에는 L6 에 의하여 x 를 삽입한 뒤에 순환문을 빠져나오고, 순환문 종료 후에는 만약 L 에 아직 원소가 남아 있다면 그것들을 모두 answer 의 끝에 가져다 붙이면 됩니다. 이 동작을 위해서는 비슷한 구조의 순환문을 하나 더 써도 되고, 아니면 리스트 슬라이싱 (예: L[pos + 1:]) 을 이용해서 리스트를 이어 붙여도 됩니다.

그런데, 여기에 얘기한 두 가지 방법 중 어느 쪽이 더 좋은 구현이 될까요? 연습을 원한다면 두 가지 (또는, 하나 하나 붙이는 방법들도 순환문을 또 쓰는 방법과 리스트를 슬라이싱하여 이어 붙이는 두 가지로 나누어 도합 세 가지) 방법을 각각 구현해서 테스트를 통과하도록 해보면 어느 구현이 더 좋을지 판단이 설 것 같습니다. 또한 좋은 프로그래밍 연습도 될 거구요.

이성원

def solution(L, x):

answer = L

for pos in range(len(L)):
if x < L[pos]:
answer.insert(pos, x)
break

elif x > L[-1]:
answer.append(x)

return answer

이렇게 바꿨습니다! 감사합니다!

답변 쓰기
이 입력폼은 마크다운 문법을 지원합니다. 마크다운 가이드 를 참고하세요.