https://school.programmers.co.kr/learn/courses/30/lessons/159994
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
def solution(cards1, cards2, goal):
answer = "Yes"
for g in goal:
if len(cards1) > 0 and g == cards1[0]:
cards1.pop(0)
elif len(cards2) > 0 and g == cards2[0]:
cards2.pop(0)
else:
answer = "No"
break
return answer
1. 입력과 목표의 관계 파악
- cards1과 cards2는 각 단어가 순서대로 배열되어 있습니다.
- goal을 순서대로 탐색하면서, 해당 단어가 cards1 또는 cards2의 맨 앞에 있는지 확인해야 합니다.
2. 구현 로직
- goal 배열을 순회
- goal의 각 단어를 하나씩 확인합니다.
- 현재 단어(current_word)를 가져옵니다.
- cards1과 cards2의 첫 번째 단어 비교
- cards1의 맨 앞 단어가 current_word와 같다면:
- cards1의 첫 번째 단어를 제거합니다.
- cards2의 맨 앞 단어가 current_word와 같다면:
- cards2의 첫 번째 단어를 제거합니다.
- 둘 다 아니면:
- goal을 만들 수 없으므로 "No"를 반환합니다.
- cards1의 맨 앞 단어가 current_word와 같다면:
- 모든 단어를 확인
- goal 배열을 끝까지 순회했다면 "Yes"를 반환합니다.
3. 힌트: 카드 제거
- cards1과 cards2에서 맨 앞의 단어를 확인하고 제거하는 동작이 필요합니다.
- 이를 위해 리스트의 첫 번째 요소를 읽고 제거하는 방식을 사용합니다.
4. 조건별 흐름 정리
단어 탐색:
- current_word가 cards1[0]과 같으면:
- cards1의 첫 번째 단어를 제거합니다.
- 아니고 current_word가 cards2[0]과 같으면:
- cards2의 첫 번째 단어를 제거합니다.
- 둘 다 아니면:
- "No"를 반환합니다.
반복 종료:
- goal의 모든 단어를 처리했다면:
- "Yes"를 반환합니다.
5. 반복문으로 처리
- goal 배열을 하나씩 확인하고 처리합니다.
- 카드 뭉치의 맨 앞 단어와 비교하며, 일치하면 제거하고 다음 단어로 이동합니다.
6. 예제 분석
예제 1:
- cards1: ["i", "drink", "water"]
- cards2: ["want", "to"]
- goal: ["i", "want", "to", "drink", "water"]
- goal[0] = "i" → cards1에서 제거.
- goal[1] = "want" → cards2에서 제거.
- goal[2] = "to" → cards2에서 제거.
- goal[3] = "drink" → cards1에서 제거.
- goal[4] = "water" → cards1에서 제거.
- 모두 처리 → "Yes".
7. 구현 시 유의할 점
- cards1과 cards2는 비어있을 수도 있으니 비교 전에 확인하세요.
- goal을 모두 처리하면 "Yes"를 반환하세요.
*
```
if len(cards1) == 0 or len(cards2) == 0: continue
```
현재 코드에서 발생하는 문제는 cards1이나 cards2 중 하나가 비어있을 때 goal의 단어를 건너뛰는 것입니다. 이로 인해 원하는 로직이 제대로 실행되지 않습니다. 이 문제를 해결하기 위해 아래 내용을 고려해 보세요:
1. 조건 순서의 문제
- if len(cards1) == 0 or len(cards2) == 0: 부분이 모든 경우를 건너뛰게 만듭니다.
- 사실 cards1 또는 cards2가 비어 있어도, 남은 단어들이 여전히 다른 리스트에 있는지 확인해야 합니다.
- 이 조건을 각 리스트가 비어 있는 경우에도 처리하도록 수정해야 합니다.
2. 리스트가 비어 있을 때 조건 추가
- cards1 또는 cards2가 비어 있을 수 있습니다. 따라서 각각의 조건을 따로 처리해야 합니다.
- 예를 들어:
- cards1이 비어 있는 경우: cards2[0]만 비교.
- cards2가 비어 있는 경우: cards1[0]만 비교.
3. 수정할 조건의 흐름
- goal의 현재 단어(g)가 cards1[0]과 같다면:
- cards1의 첫 번째 단어를 제거합니다.
- goal의 현재 단어가 cards2[0]과 같다면:
- cards2의 첫 번째 단어를 제거합니다.
- 두 리스트가 모두 비어 있을 경우를 따로 건너뛰지는 않도록 해야 합니다.
4. 중요한 점
- cards1.remove(g) 대신 pop(0)을 사용하세요.
- remove는 리스트에서 해당 값을 찾아 제거하는 데 시간 복잡도가 O(n)이라 비효율적입니다.
- pop(0)은 첫 번째 값을 제거하므로 문제의 요구사항에 맞고, 논리적으로도 더 깔끔합니다.
- cards1이나 cards2가 비어 있는 경우에도 오류가 나지 않도록 각각의 조건을 개별적으로 처리해야 합니다.
지금 코드에서 발생하는 문제는 answer의 값을 "No"로 설정한 뒤에도 반복문이 계속 진행되고, 마지막에 answer = "Yes"로 덮어쓰여지는 데에 있습니다. 이로 인해 원하는 조건이 충족되지 않았음에도 불구하고 "Yes"가 반환됩니다.
문제의 원인
- else 블록에서 answer = "No"로 설정했지만, continue를 사용하면서도 루프가 끝날 때 마지막에 answer = "Yes"가 실행됩니다.
- 반복문이 끝날 때까지 모든 조건을 만족했는지 확인하지 않고, 무조건 "Yes"로 설정하기 때문에 잘못된 결과가 나옵니다.
해결 방법
- 반복문을 즉시 종료
- goal 배열을 처리하다가 조건을 만족하지 않는 경우, 더 이상 확인할 필요가 없으므로 즉시 "No"를 반환해야 합니다.
- continue가 아닌, return "No"를 사용하면 문제를 해결할 수 있습니다.
- answer 변수를 제거
- 불필요하게 answer를 계속 업데이트할 필요가 없습니다.
- 조건이 만족되지 않는 경우 바로 "No"를 반환하고, 반복문을 끝까지 수행했다면 "Yes"를 반환하면 됩니다.
수정된 코드 흐름
- goal의 현재 단어(g)가:
- cards1의 첫 번째 단어와 같으면 제거.
- cards2의 첫 번째 단어와 같으면 제거.
- 두 리스트의 첫 번째 단어와도 같지 않으면 즉시 "No"를 반환.
- 반복문을 끝까지 수행하면 "Yes"를 반환.
'알고리즘 > Programmers' 카테고리의 다른 글
[프로그래머스] 없는 숫자 더하기 (Python) (1) | 2024.12.12 |
---|---|
[프로그래머스] 기사단원의 무기 (Python) (0) | 2024.12.12 |
[프로그래머스] 2018 KAKAO BLIND RECRUITMENT[1차] | 다트 게임 (Python) (0) | 2024.12.10 |
[프로그래머스] 대충 만든 자판 (Python) (2) | 2024.12.09 |
[프로그래머스] 해시 | 폰켓몬 (Python) (0) | 2024.12.09 |