본문 바로가기
알고리즘/프로그래머스

프로그래머스 Lv1 달리기 경주 (python)

by 개발하는 호랑이 2024. 2. 2.

달리기 경주

풀이

처음엔 위 문제를 보고 간단하게 a[0],a[1] = a[1], a[0] 을 사용하면 되겠다 하고 아래 처럼 풀었다.
그런데 시간초과가 발생했다....

# 자기 바로 앞의 선수를 추월 할 추월한 선수의 이름을 부름
# 만약 현재 2등 선수의 이름이 불러졌다번 1등 선수를 제치고 1등이 된거니
# win[1], win[2] = win[2], win[1] 이 됨
def solution(players, callings):
    N = len(callings)
    for i in range(N):
        k = players.index(callings[i])
        players[k], players[k-1] = players[k-1], players[k]
    return players

그래서 다른 방법을 찾았다.
딕셔너리에 값을 저장 시키는 방법이다.
하나로는 내 머리에서 도저히 방법이 안나와서 2개의 딕셔너리를 사용했다.
1. 선수와 순번, 순번과 선수로 딕셔너리 생성
2. callings에서 calling 될 때 마다 콜링받은 선수와 함께 콜링받은 선수 순번을 확인
3. 2를 토대로 i_vs_p에서 전 번 선수를 찾아내고, 선수:순번 딕셔너리에서 각 2명의 순번을 바꿔주기
4. 순번이 바꿔졌으니, 순번:선수 딕셔너리에서도, 앞 뒤 서로의 값을 바꿔주기
5. 2.3.4.의 반복이 종료되면, 순번:선수를 이용해서 각 순번대로 선수를 출력시키기.

def solution(players, callings):
    N = len(players)
    M = len(callings)
    # 딕셔너리로 선수와 순서를 매칭
    p_vs_i = {player: i for i, player in enumerate(players)}
    # 딕셔너리로 순서와 선수를 매칭
    i_vs_p = {i: player for i, player in enumerate(players)}

    # 콜링될때마다 해당 선수와 다른 선수 매칭
    for calling in callings:
        # 콜링받은 선수 순서 확인
        i = p_vs_i[calling]
        # 불린 선수와 그 앞의 선수 위치 바꾸기
        p_vs_i[calling] = i - 1
        p_vs_i[i_vs_p[i - 1]] = i

        i_vs_p[i], i_vs_p[i - 1] = i_vs_p[i - 1], i_vs_p[i]

    return [i_vs_p[i] for i in range(len(players))]

다른 사람 풀이

나와 다르게 딕셔너리 하나만을 이용했다.(원래 내가 하고 싶었던 건데 이렇게 구현해야했구만 흑흑)
선수:순번의 딕셔너리를 사용했다.
1. 선수:순번의 딕셔너리를 이용해서 순번을 구한다.
2. 현재 콜링된 선수는 딕셔너리에서 1칸 빠르게 달림으로 한다.
3. players에서 선수를 확인하고, 선수:순번 딕셔너리에서 선수의 순번을 1칸 느리게 달림으로 한다.
4. players를 건드려서 players[c-1], players[c] = players[c], players[c-1] 로 재조정한다.
5. 2~4가 끝나면 players를 출력한다.

이렇게 하려고 했는데 머리가 꼬이는 바람에 어떻게 해야하는지 도저히 감이 안왔다. 이제라도 감이 와서 다행이다.

def solution(players, callings):
    pla_dic = {key: i for i, key in enumerate(players)}

    for p in callings:
        c = pla_dic[p]
        pla_dic[p] -= 1
        pla_dic[players[c-1]] += 1
        players[c-1], players[c] = players[c], players[c-1]

    return players