[프로그래머스][LV.1] 카드 뭉치 | python

2025. 1. 23. 17:48프로그래머스/LV.1

 

문제 링크: 카드 뭉치

 

문제 설명

문제 설명

코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
한 번 사용한 카드는 다시 사용할 수 없습니다.카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.

예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.
문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.

제한사항

-1 ≤ cards1의 길이, cards2의 길이 ≤ 10
  • 1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
    cards1과 cards2에는 서로 다른 단어만 존재합니다.

2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이

  • 1 ≤ goal[i]의 길이 ≤ 10
    goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.

cards1, cards2, goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다

 


문제 풀이

def solution(cards1, cards2, goal):
    
    for word in cards1:
        if goal:
            if cards2:
                while cards2[0]==goal[0]:
                    del goal[0]
                    del cards2[0]
            if word==goal[0]:
                del goal[0]
    if goal:
        answer='No'
    else:
        answer='Yes'

처음엔 이렇게 풀었는데 인덱스에러도 나고 생각해보니 word==goal[0]:에서 논리가 틀림.



cards1과 cards2가 최대 각 10개씩 원소를 갖는다. 어느 한쪽에서 10개가 먼저나올때를 대비해 while문은 20개까지만 돈다.
goal의 맨 앞 값이 cards1이나 cards2의 맨 앞 값과 같으면 둘 다 삭제해서 맨 앞값만으로 비교할 수 있게 한다.

루프를 다 돌고 goal에 값을 확인하여 리턴한다.

 

내코드

def solution(cards1, cards2, goal):
    i=0
    while i<20 and goal:
        i+=1
        if cards1:
            if cards1[0]==goal[0]:
                del goal[0]
                del cards1[0]
        if cards2:
            if cards2[0]==goal[0]:
                del goal[0]
                del cards2[0]
    
    if goal:
        answer='No'
    else:
        answer='Yes'
    return answer

 

 


더보기

다른사람풀이

def solution(cards1, cards2, goal):
    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:
            return "No"
    return "Yes"

goal값을 돌면서 cards의 맨 앞값과 비교하여 조건에 맞을대 pop을 이용하여 맨 앞값을 뺀다. pop()에 인덱스 값을 넣으면 해당 인덱스의 원소값을 뺀다는 기능이 있다는 건 처음 알았다. 기억해 놔야지.

 

def solution(cards1, cards2, goal):
    idx1,idx2=0,0
    for word in goal:
        if len(cards1)>idx1 and cards1[idx1]==word:
            idx1+=1
        elif len(cards2)>idx2 and cards2[idx2]==word:
            idx2+=1
        else:
            return "No"
    return "Yes"

인덱스값을 활용한 풀이이다. 원소값을 삭제하는 것보다 인덱스를 활용하는게 시간이 덜 걸릴 것 같기도...?

둘 다에 해당하지 않으면 return으로 바로 No를 출력하는게 좋은 방법같다.

 

from collections import deque

def solution(cards1, cards2, goal):
    card1_q = deque(list(cards1))
    card2_q = deque(list(cards2))

    for target in goal:
        if card1_q and card1_q[0] == target:
            card1_q.popleft()
        elif card2_q and card2_q[0] == target:
            card2_q.popleft()
        else:
            return "No"

    return "Yes"

데큐를 활용한 방법. 검색해보니 데큐가 시간복잡도가 굉장히 빠르단다.

 

♣ deque

deque는 Python의 collections 모듈에서 제공하는 양방향 큐(double-ended queue) 자료구조입니다. 이는 리스트(list)와 비슷하지만, 양쪽 끝에서의 삽입과 삭제 연산이 매우 효율적인 특징이 있습니다.

 

 

  • 빠른 삽입과 삭제:
    • 리스트의 경우 양 끝이 아닌 중간에서 요소를 삽입/삭제하면 O(n)O(n)의 시간이 걸립니다.
    • 하지만 deque는 양쪽 끝에서 삽입/삭제하는 연산이 O(1)O(1)로 매우 빠릅니다.
  • 양방향 처리:
    • deque는 큐(선입선출)와 스택(후입선출) 모두의 동작을 지원합니다.
    • 큐처럼 앞쪽에서 값을 제거하거나, 스택처럼 뒤쪽에서 값을 추가하거나 제거할 수 있습니다.
  • 사용 메서드:
    • append(x): 오른쪽 끝에 요소 x 추가.
    • appendleft(x): 왼쪽 끝에 요소 x 추가.
    • pop(): 오른쪽 끝에서 요소 제거 및 반환.
    • popleft(): 왼쪽 끝에서 요소 제거 및 반환.
    • extend(iterable): 오른쪽 끝에 iterable 요소를 추가.
    • extendleft(iterable): 왼쪽 끝에 iterable 요소를 추가.
card1_q = deque(list(cards1))
card2_q = deque(list(cards2))

 

  • deque(list(cards1))와 deque(list(cards2))는 리스트를 deque로 변환합니다.
  • 이를 통해 cards1과 cards2를 큐처럼 사용하여 요소를 앞에서 제거하거나 검사할 수 있습니다.