https://school.programmers.co.kr/learn/courses/30/lessons/258711
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
무관한 정점의 진입차수는 0이고 진출차수는 2 이상이다.
무관한 정점의 진출차수는 도넛/막대/8자 그래프 수의 합이다.
무관한 정점을 제거한 후 진입차수가 0인 정점의 수는 막대그래프의 수와 같다.
무관한 정점을 제거한 후 진입차수가 2인 정점의 수는 8자그래프의 수와 같다.
도넛그래프의 수는 총 그래프 수 - 막대그래프수 - 8자그래프수이다.
테스트 8부터 26까지 시간초과 뜬 코드(나머지는 정답)
비록 시간초과는 떴지만 그래프의 정점과 간선의 개수를 조회하는 알고리즘을 작성해볼 수 있었다.
import copy
# start번째 정점이 포함된 그래프의 정점 리스트 반환
def getGetGraphVertexList(graph, vertexList, start):
방문여부 = {v: False for v in vertexList}
q = [start]
while len(q) > 0:
x = q.pop(0)
방문여부[x] = True
for y in vertexList:
if graph[x][y] and not 방문여부[y]:
q.append(y)
return list(dict(filter(lambda x: x[1], 방문여부.items())).keys())
# 그래프의 정점수, 간선수 조회
def getVertexCntAndEdgeCnt(graph, graphVertexList):
정점수 = len(graphVertexList)
간선수 = 0
for i in graphVertexList:
for j in graphVertexList:
if graph[i][j]:
간선수 += 1
return (정점수, 간선수)
# 그래프 제거
def deleteGraph(graph, vertexList, graphVertexList):
for i in graphVertexList:
for j in graphVertexList:
if graph[i][j]:
graph[i][j] = False
for i in graphVertexList:
vertexList.remove(i)
def solution(edges):
# 정점리스트, 정점 최대값 조회
vertexList = set()
for (i, j) in edges:
vertexList.add(i)
vertexList.add(j)
vertexList = list(dict.fromkeys(vertexList))
sorted(vertexList)
maxV = vertexList[-1]
# edges를 graph(인접행렬)로 변환
graph = [[False for j in range(maxV+1)] for i in range(maxV+1)]
for (i, j) in edges:
graph[i][j] = True
# 진입/진출 차수 세기
진입진출차수 = {}
for i in vertexList:
진출차수 = 진입차수 = 0
for j in vertexList:
if graph[i][j]:
진출차수 += 1
if i != j and graph[j][i]:
진입차수 += 1
진입진출차수[i] = (진입차수, 진출차수)
# 무관한 정점 찾기
무관한정점 = 0
for k, v in 진입진출차수.items():
진입차수, 진출차수 = v
if 진입차수 == 0 and 진출차수 >= 2:
무관한정점 = k
# 무관한 정점 제거
for i in vertexList:
graph[무관한정점][i] = False
vertexList.remove(무관한정점)
# 도넛그래프, 팔자그래프 찾기
도넛그래프수 = 팔자그래프수 = 0
남은정점들 = copy.deepcopy(vertexList)
for i in vertexList:
if i not in 남은정점들:
continue
graphVertexList = getGetGraphVertexList(graph, 남은정점들, i)
vc, ec = getVertexCntAndEdgeCnt(graph, graphVertexList)
if vc == ec:
도넛그래프수 += 1
deleteGraph(graph, 남은정점들, graphVertexList)
elif vc < ec:
팔자그래프수 += 1
deleteGraph(graph, 남은정점들, graphVertexList)
# 막대그래프 찾기
# 막대그래프수 = 진입차수 없는 정점 개수
막대그래프수 = 0
for i in 남은정점들:
진입차수 = 0
for j in 남은정점들:
if graph[j][i]:
진입차수 += 1
if 진입차수 == 0:
막대그래프수 += 1
return [무관한정점, 도넛그래프수, 막대그래프수, 팔자그래프수]
최종통과한 코드
MAX_CNT = 1000001
def solution(edges):
진입차수 = [0] * MAX_CNT
진출차수 = [0] * MAX_CNT
정점들 = set()
for (i, j) in edges:
진입차수[j] += 1
진출차수[i] += 1
정점들.add(i)
정점들.add(j)
정점들 = list(정점들)
무관한정점 = 0
for i in 정점들:
if 진입차수[i] == 0 and 진출차수[i] >= 2:
무관한정점 = i
break
# 그래프수 조회
그래프수 = 진출차수[무관한정점]
# 무관한 정점에 의한 진입차수 제거
for (i, j) in edges:
if i == 무관한정점:
진입차수[j] -= 1
정점들.remove(무관한정점)
# 막대그래프수(진입차수가 0인 정점수) 조회
막대그래프수 = 0
for i in 정점들:
if 진입차수[i] == 0:
막대그래프수 += 1
# 팔자그래프수(진입차수가 2인 정점수) 조회
팔자그래프수 = 0
for i in 정점들:
if 진입차수[i] == 2:
팔자그래프수 += 1
# 도넛그래프수(그래프수 - 막대그래프수 - 팔자그래프수) 조회
도넛그래프수 = 그래프수 - 막대그래프수 - 팔자그래프수
return [무관한정점, 도넛그래프수, 막대그래프수, 팔자그래프수]
[백준] 10845. 큐 | 큐 | 파이썬, 정답 소스코드 (2) | 2024.10.09 |
---|---|
[백준] 9012. 괄호 | 스택 | 파이썬, 정답 소스코드 (1) | 2024.10.09 |
[프로그래머스] 258712. 가장 많이 받은 선물| 구현 | 파이썬, 소스코드, 정답 (1) | 2024.03.26 |
[LeetCode] Combination Sum | DFS | 파이썬 알고리즘 인터뷰, 정답, 소스코드 (2) | 2023.06.22 |
[LeetCode] Longest Substring Without Repeating Characters | 투포인터 | 파이썬 알고리즘 인터뷰, 정답, 소스코드 (1) | 2023.06.19 |