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. 구현 로직

  1. goal 배열을 순회
    • goal의 각 단어를 하나씩 확인합니다.
    • 현재 단어(current_word)를 가져옵니다.
  2. cards1과 cards2의 첫 번째 단어 비교
    • cards1의 맨 앞 단어가 current_word와 같다면:
      • cards1의 첫 번째 단어를 제거합니다.
    • cards2의 맨 앞 단어가 current_word와 같다면:
      • cards2의 첫 번째 단어를 제거합니다.
    • 둘 다 아니면:
      • goal을 만들 수 없으므로 "No"를 반환합니다.
  3. 모든 단어를 확인
    • 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"]
  1. goal[0] = "i" → cards1에서 제거.
  2. goal[1] = "want" → cards2에서 제거.
  3. goal[2] = "to" → cards2에서 제거.
  4. goal[3] = "drink" → cards1에서 제거.
  5. goal[4] = "water" → cards1에서 제거.
  6. 모두 처리 → "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. 수정할 조건의 흐름

  1. goal의 현재 단어(g)가 cards1[0]과 같다면:
    • cards1의 첫 번째 단어를 제거합니다.
  2. goal의 현재 단어가 cards2[0]과 같다면:
    • cards2의 첫 번째 단어를 제거합니다.
  3. 두 리스트가 모두 비어 있을 경우를 따로 건너뛰지는 않도록 해야 합니다.

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"로 설정하기 때문에 잘못된 결과가 나옵니다.

해결 방법

  1. 반복문을 즉시 종료
    • goal 배열을 처리하다가 조건을 만족하지 않는 경우, 더 이상 확인할 필요가 없으므로 즉시 "No"를 반환해야 합니다.
    • continue가 아닌, return "No"를 사용하면 문제를 해결할 수 있습니다.
  2. answer 변수를 제거
    • 불필요하게 answer를 계속 업데이트할 필요가 없습니다.
    • 조건이 만족되지 않는 경우 바로 "No"를 반환하고, 반복문을 끝까지 수행했다면 "Yes"를 반환하면 됩니다.

수정된 코드 흐름

  1. goal의 현재 단어(g)가:
    • cards1의 첫 번째 단어와 같으면 제거.
    • cards2의 첫 번째 단어와 같으면 제거.
  2. 두 리스트의 첫 번째 단어와도 같지 않으면 즉시 "No"를 반환.
  3. 반복문을 끝까지 수행하면 "Yes"를 반환.

+ Recent posts