프로그래머스_섬 연결하기(재풀이)

임정민·2023년 11월 6일
0

알고리즘 문제풀이

목록 보기
121/173
post-thumbnail

프로그래머스 Lv3 문제입니다. 실전에 대비하기 위해 60분 시간제한을 두고 풀었습니다.

문제

https://school.programmers.co.kr/learn/courses/30/lessons/42861

[나의 풀이]

⌛ 17분 소요


def find_parent(parent,x):
    
    if parent[x] != x:
        parent[x] = find_parent(parent,parent[x])
        
    return parent[x]

def union_parent(parent,start,end):
    
    start = find_parent(parent,start)
    end = find_parent(parent,end)

    if start<end:
        parent[end] = start
    else:
        parent[start] = end
    
def solution(n,costs):
    
    answer = 0
    
    islands = [i for i in range(n)]
    # print(islands)
    
    costs = sorted(costs, key=lambda x:x[2])
    print("costs : ",costs)
    
    for cost in costs:
        start,end,fee = cost
        print("islands : ",islands)
        print("start : ",start, " end : ",end)
        # start 와 end는 모두 연결이 가능
        # but, 부모가 다르면 크루스칼 연결이 안된 상태 => 어느 한쪽에 속하게 해야함
        if find_parent(islands,start) != find_parent(islands,end):
            print("if")
            union_parent(islands,start,end)
            answer += fee
        
    return answer

모든 노드를 연결할 수 있는 최소 비용 방법을 구현하는 크루스칼 알고리즘 문제입니다.

먼저 연결된 두 섬간의 이동 비용이 적은 순으로 정렬하였습니다. 그후 자기 자신 노드의 맨 끝단 노드를 찾는 find_parent 함수와 두 노드 집합을 연결하는 union_parent 함수를 활용하여 구현하였습니다.

이전에 풀어본 알고리즘으로 어렵지 않게 구현할 수 있었습니다.

[다른 사람의 풀이1]


def ancestor(node, parents):
    if parents[node] == node:
        return node
    else:
        return ancestor(parents[node], parents)

def solution(n, costs):
    answer = 0
    edges = sorted([(x[2], x[0], x[1]) for x in costs])
    parents = [i for i in range(n)]
    bridges = 0
    for w, f, t in edges:
        if ancestor(f, parents) != ancestor(t, parents):
            answer += w
            parents[ancestor(f, parents)] = t
            bridges += 1
        if bridges == n - 1:
            break
    return answer

'나의 풀이'처럼 크루스칼 알고리즘을 활용하되 최소 비용으로 연결하는 과정에서 일정 조건을 걸고 break하여 더욱 빠른 풀이였습니다.

모든 N개의 섬을 연결하기 위해서 N-1개의 선만 있으면 되기때문에 선의 갯수를 파악하는 방법으로 구현하는 인상적인 풀이였습니다.

[다른 사람의 풀이2]


def solution(n, costs):
    answer = 0
    costs.sort(key = lambda x: x[2]) 
    link = set([costs[0][0]])

    # Kruskal 알고리즘으로 최소 비용 구하기
    while len(link) != n:
        for v in costs:
            if v[0] in link and v[1] in link:
                continue
            if v[0] in link or v[1] in link:
                link.update([v[0], v[1]])
                answer += v[2]
                break
                
    return answer

set()을 활용하여 포함관계를 파악하는 크루스칼 알고리즘의 다른 표현 방식입니다.

최소 비용순으로 이동가능한 섬 리스트를 정렬한뒤 link 라는 set() 자료형에 시작점을 넣은 후 섬 이동가능한 섬 리스트를 돌며 시작점,도착점이 이미 link에 포함되어 있다면 이미 연결된 섬들 이므로 continue하고 아니라면 link에 포함하고 비용을 추가하는 방식입니다.

여기서 포인트는 '나의 풀이'에서는 find_parent, union_parent 함수로 섬을 연결하고 비용을 추가할지 여부를 판단했다면 위 풀이는 시작점,도착점이 이미 연결되어 있는지에 대해서는 포함관계로 파악하였다는 점입니다.

감사합니다.

profile
https://github.com/min731

0개의 댓글