Sad Puppy 3 'CodingTest/문제 풀이 - Python' 카테고리의 글 목록 (5 Page) :: 개발자 아지트

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

문제설명

n개의 송전탑이 전선을 통해 하나의 트리 형태로 연결되어 있습니다. 당신은 이 전선들 중 하나를 끊어서 현재의 전력망 네트워크를 2개로 분할하려고 합니다. 이때, 두 전력망이 갖게 되는 송전탑의 개수를 최대한 비슷하게 맞추고자 합니다.

 

송전탑의 개수 n, 그리고 전선 정보 wires가 매개변수로 주어집니다. 전선들 중 하나를 끊어서 송전탑 개수가 가능한 비슷하도록 두 전력망으로 나누었을 때, 두 전력망이 가지고 있는 송전탑 개수의 차이(절대값) return 하도록 solution 함수를 완성해주세요.

 

문제 해결 방법

 

그래프로 구현하고 dfs로 송전탑의 개수를 세아렸다. 

 

코드 구현

 

def dfs(newGraph, visited, node):
    visited[node] = True
    cnt=1
    for injeop in newGraph[node]:
        if visited[injeop] == False:
            cnt += dfs(newGraph, visited, injeop)
    return cnt


def solution(n, wires):
    answer = -1
    
    # 그래프 생성
    graph = [[] for _ in range(n+1)]
    for v1, v2 in wires:
        graph[v1].append(v2)
        graph[v2].append(v1)
    
    
    Totalcntlist = []
    for i in range(1, n+1):
        for value in graph[i]:
            # print('어디보자---^^^')
            # print('graph[', i, ']: ', graph[i], 'value: ',value)
            idxOne = graph[value].index(i)
            graph[value].remove(i) 
            idxTwo = graph[i].index(value)
            graph[i].remove(value)
            
            cntlist=[]
            visited = [False] * (n+1)
            for j in range(1, n+1):
                if visited[j] == False:
                    cnt = dfs(graph, visited, j)
                    cntlist.append(cnt)     
            # print(cntlist)
            sum = abs(cntlist[0]-cntlist[1])
            Totalcntlist.append(sum)
            
            # graph[value].append(i) # 문제의 코드 
            # graph[i].append(value)  
            # print('graph[', i, ']: ', graph[i])
            # print('결과보자 ---vvv')
            graph[value].insert(idxOne, i)
            graph[i].insert(idxTwo, value)
            
    answer = min(Totalcntlist)
    return answer

 

 

 

문제의 코드 

 

더보기

 

문제의 코드 1. 

 

import copy
def dfs(newGraph, visited, node):
    visited[node] = True
    cnt=1
    for injeop in newGraph[node]:
        if visited[injeop] == False:
            cnt += dfs(newGraph, visited, injeop)
    return cnt

def solution(n, wires):
    answer = -1
    graph = [[] for _ in range(n+1)]
    for v1, v2 in wires:
        graph[v1].append((v2))
        graph[v2].append((v1))
    originGraph = copy.deepcopy(graph)
    # 설마 일일이 다 끊어서 dfs구하라 그건가? ;; 방문은 visited로 한다. 
    
    newgraph = copy.deepcopy(originGraph)
    #print(newgraph)
    Totalcntlist = []
    for i in range(1, n+1):
        # 끊는 대상 = i
        # index가 i 인곳에서 연결된거 다 빼야함
        for value in newgraph[i]:
            newgraph[value].remove(i)
            newgraph[i].remove(value)
    
            #print('i:', i,'value', value,': ',newgraph)
            # 이때 나온 그래프로 dfs를 하면됨 
            
            cntlist=[]
            visited = [False] * (n+1)
            for j in range(1, n+1):
                if visited[j] == False:
                    cnt = dfs(newgraph, visited, j)
                    cntlist.append(cnt)
            #print('cntlist', cntlist)
            sum = abs(cntlist[0]-cntlist[1])
            Totalcntlist.append(sum)
            newgraph[value].append(i)
            newgraph[i].append(value)
            #newgraph = copy.deepcopy(originGraph) # deppcopy때문
    #print('Totalcntlist', min(Totalcntlist))    
    answer = min(Totalcntlist)
    return answer

 

 

 

문제의 코드 2.

 

import copy
def dfs(newGraph, visited, node):
    visited[node] = True
    cnt=1
    for injeop in newGraph[node]:
        if visited[injeop] == False:
            cnt += dfs(newGraph, visited, injeop)
    return cnt

def solution(n, wires):
    answer = -1
    graph = [[] for _ in range(n+1)]
    for v1, v2 in wires:
        graph[v1].append(v2)
        graph[v2].append(v1)
    # 설마 일일이 다 끊어서 dfs구하라 그건가? ;; ㅅㅂ ㅠㅠ 방문은 visited로 한다. 
    
    #print(newgraph)
    Totalcntlist = []
    for i in range(1, n+1):
        # 끊는 대상 = i
        # index가 i 인곳에서 연결된거 다 빼야함
        for value in graph[i]:
            graph[value].remove(i)
            graph[i].remove(value)
    
            
            cntlist=[]
            visited = [False] * (n+1)
            for j in range(1, n+1):
                if visited[j] == False:
                    cnt = dfs(graph, visited, j)
                    cntlist.append(cnt)
            #print(cntlist)
            sum = abs(cntlist[0]-cntlist[1])
            Totalcntlist.append(sum)
            
            graph[value].append(i)
            graph[i].append(value)  
            
    answer = min(Totalcntlist)
    return answer

 

 

 

시간/공간 복잡도

 

O(N^2)

 

최적화 및 개선

 

따로 하지않음

 

어려웠던 점

진짜 로직 구현은 어찌저찌 잘 해결했어도, graph 간선끊었다가 원상복구 하는 부분에서 애를 많이 먹었다. 

처음에 간선 끊고 원상복구를 하려고 일반 리스트에 그냥 대입연산자로 대입을 했었는데, 웬걸 먹히지 않았다. 

 

파이썬에서 immutable한 특징을 가진 자료형(예를들면, int)의 경우, 객체 생성이 된 후 값 수정이 불가하다. 

따라서 처음에 값을 선언한 후 다른 변수에 값을 대입하고 그 변수의 값을 변경해도, 처음 선언한 변수의 값은 변하지 않는다. 

 

반대로, muteable한 객체는 다르다. (예를들면, list)

처음에 리스트를 선언한 후 다른 변수에 리스트를 대입하고 그 변수의 값 일부를 변경하면, 처음 선언한 리스트의 값 일부까지 변한다.  

 

처음 선언한 리스트는 a리스트이고, 다른 변수 리스트는 b라고 가정한다. 

이 경우에서는 리스트 a와 리스트 b는 같은 주소를 참조한다. 따라서 b 리스트의 요소가 변경되면, a 리스트도 똑같이 변경된다. 

 

그래서 찾아보니 deepcopy를 해야한다고 했다.

 

deepcopy로 문제를 풀어보니 전보단 확실히 정답률이 높아졌는데 몇몇 테스트 케이스가 틀렸다. 확인해보니 deepcopy를 제대로 못쓰고 있는것 같이 계속 특정 부분에서 구멍이 났다. 그래서 일일이 끊은 간선을 다시 붙여주는 작업을 했다. 

 

그 작업에서 append를 사용했더니 원래 있던 자리에서 원소가 맨 뒤에 붙었다. 이게 이제 그래프 순환할때 문제가 됐다. 

특정 테스트 케이스의 경우 자꾸 어떤 경우만 빼고 dfs를 진행해서 틀렸다. 

 

이 문제를 해결하고 나니 deepcopy 가 왜 안됐었는지 알 것같았다. 

 

경로를 아무리 끊는다고 해도 순환할 때의 기준이 되는 기준점은 변경되면 안된다. 

 

코드로 설명하면 다음과 같다. 

 

import copy
def dfs(newGraph, visited, node):
    visited[node] = True
    cnt=1
    for injeop in newGraph[node]:
        if visited[injeop] == False:
            cnt += dfs(newGraph, visited, injeop)
    return cnt


def solution(n, wires):
    answer = -1
    
    # 그래프 생성
    graph = [[] for _ in range(n+1)]
    for v1, v2 in wires:
        graph[v1].append(v2)
        graph[v2].append(v1)
    
    newGraph = copy.deepcopy(graph)
    
    Totalcntlist = []
    for i in range(1, n+1):
        for value in graph[i]: # 기준점 graph는 변경되면 안된다. 
            idxOne = newGraph[value].index(i)
            newGraph[value].remove(i) 
            idxTwo = newGraph[i].index(value)
            newGraph[i].remove(value)
            
            cntlist=[]
            visited = [False] * (n+1)
            for j in range(1, n+1):
                if visited[j] == False:
                    cnt = dfs(newGraph, visited, j)
                    cntlist.append(cnt)     
            sum = abs(cntlist[0]-cntlist[1])
            Totalcntlist.append(sum)      
            
            newGraph = copy.deepcopy(graph)
            
    answer = min(Totalcntlist)
    return answer

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

링크 참고

 

 

문제 해결 방법

 

다익스트라알고리즘을 적용해 문제를 해결하였음

 

 

 

코드 구현

 

def solution(N, road, K):
    answer = 0
    
    distances = [float("inf")] * (N+1) 
    distances[0] = 0 # 0과 1은 사용하지 않음
    distances[1] = 0
    
    
    for i in range(N-1):
        for i in range(1, N+1):
            for nodeSet in road:
                fromm, to, weight = nodeSet
                if fromm == i:
                    distance = distances[i] + weight
                    if distance < distances[to]:
                        distances[to] = distance

                to, fromm, weight = nodeSet
                if fromm == i:
                    distance = distances[i] + weight
                    if distance < distances[to]:
                        distances[to] = distance
                    

    # N개의 마을 중에서 K시간 이하로 배달이 가능한 마을에서만 주문을 받으려고함
    # 1번 마을에 있는 음식점이 음식 주문을 받을 수 있는 마을의 개수를 return 
    
    # a, b = 마을의 번호 c = 도로를 지나는데 걸리는 시간
    
    # 그래프 만들기 
    answer +=1
    for i in distances:
        if i <= K and i>0:
            answer+=1
    
    return answer

 

 

 

시간/공간 복잡도

O((N+E)N)

 

최적화 및 개선

하지않음... 

 

 

어려웠던 점

 

양방향 이동이라는 점을 잘 새겨봤어야 했다. 코드를 짜다보니 나도 모르게 단방향으로 코드를 작성했다. 

다익스트라 알고리즘은 n-1번 반복해야 하는 것을 잘 기억해야겠다. 

처음에 코드 작성후, 채점하니 40점이 나왔는데 혹시나 해서 최단거리 구하는 코드를 한번더 복사 붙여넣기 한 후 채점하니 50점이 나왔다. 그 후 힌트를 얻기위해 책을 한번더 보고, 그 후 한번 더 복사 붙여넣기 하니 80점이 나왔는데 그때 깨달았다.. 

 

 

 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

네트워크란 컴퓨터 상호 간에 정보를 교환할 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A 컴퓨터 B 직접적으로 연결되어있고, 컴퓨터 B 컴퓨터 C 직접적으로 연결되어 있을 컴퓨터 A 컴퓨터 C 간접적으로 연결되어 정보를 교환할 있습니다. 따라서 컴퓨터 A, B, C 모두 같은 네트워크 상에 있다고 있습니다.

 

컴퓨터의 개수 n, 연결에 대한 정보가 담긴 2차원 배열 computers 매개변수로 주어질 , 네트워크의 개수를 return 하도록 solution 함수를 작성하시오.

 

문제 해결 방법

 

 

이런 문제는 최적의 해 보다는 모든 요소를 탐색하는 것이 목적이다.

모든 요소를 탐색하기 위해 DFS가 좋다. 

 

computers를 그래프로 표현한 후, 방문 테이블을 만들고, 방문 테이블을 통해 그래프를 DFS로 몇번 탐색 했는지를 출력하면 된다. 

 

 

 

이 문제를 bfs로 풀려고 했던 과거의 내자신 ㅠㅠ 

 

 

 

코드 구현

 

주석 없는 버전

더보기

 

def dfs(computers, visited, node):
        visited[node] = True
        for idx, connected in enumerate(computers[node]):
            if connected and not visited[idx]:
                dfs(computers, visited, idx)

def solution(n, computers):
    answer = 0
    visited = [False] * n
    
    for i in range(n):
        if not visited[i]:
            dfs(computers, visited, i)
            answer += 1
    
    
    return answer

 

 

 

 

 

 

def dfs(computers, visited, node):
    # 조회를 하면 해당 노드에 대해 방문처리를 해준다. 
    # 해당 노드를 통해 computers에 딸린 다른 노드들을 반복문을 통해 조회하고,
        # 연결 여부와 방문 여부를 확인한다. 
    # 연결된 것을 통해 깊이 우선 탐색을 계속 해나간다. 
    visited[node] = True
    for index, connected in enumerate(computers[node]):
        if connected and visited[index] == False:
            dfs(computers, visited, index)
    
def solution(n, computers):
    answer = 0
    # 방문여부를 담는 크기 n만큼의 배열 
    
    visited = [False] * n
    
    for i in range(n):
        if visited[i] == False:
            dfs(computers, visited, i)
            answer+=1
    # 반복문을 통해 노드를 0~n까지 순회하며 깊이 우선 탐색을 한다. 
        # 깊이 우선 탐색 dfs에는 computers라는 그래프와, visited, 그리고 노드를 보내준다. 
    # 깊이 우선 탐색이 끝나면 answer +1 을 해준다. 
    return answer

 

 

시간/공간 복잡도

 

O(N^2)

 

 

최적화 및 개선

 

따로 하지 않음.


어려웠던 점

 

아직 DFS, BFS사용에 서툰것 같다. 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

 

링크 참고


문제 해결 방법

 

bfs를 통해 문제를 해결하였음

 

 

코드 구현

 

 

과거에 작성한 코드 

더보기
from collections import deque

def solution(maps):
    answer = 0
    # map은 2차원 배열이라고 생각하면 됨 
    n = len(maps) #가로 
    m = len(maps[0]) #세로 

    # 이동할 네 가지 방향 정의 (상, 하, 좌, 우)
    dx = [-1, 1, 0, 0] #세로축
    dy = [0, 0, -1, 1] #가로축 
    
    def bfs(x,y):
        #큐 구현을 위해 deque라이브러리 사용
        queue = deque()
        queue.append((x,y))
        # 큐가 빌 때까지 반복하기 
        while queue:
            x, y = queue.popleft()
            for i in range(4):
                nx = x + dx[i]
                ny = y + dy[i]
                # 공간을 벗어난 경우 무시
                if nx  < 0 or nx >= n or ny < 0 or ny >= m:
                    continue
                # 벽인 경우 무시
                if maps[nx][ny] == 0:
                    continue
                # 해당 노드를 처음 방문하는 경우에만 최단 거리 기록 
                if maps[nx][ny] == 1:
                    maps[nx][ny] = maps[x][y] + 1
                    queue.append((nx, ny))
        # 가장 오른쪽 아래 까지의 최단 거리 반환 
        return maps[n-1][m-1]
    
    
    if bfs(0,0)==1:
        answer=-1
    else:
        answer=bfs(0,0)
    
    return answer

 

 

 

 

 

from collections import deque

def solution(maps):
    answer = 0
    n = len(maps) 
    m = len(maps[0]) 
    
    # 최단 거리 구하기.
    # bfs - deque
    # 1,1 부터 시작
    dx = [1, -1, 0, 0] # 동, 서, 남, 북
    dy = [0, 0, -1, 1]
    
    # 게임 맵 벗어난 길은 갈 수 없음
    queue = deque([(0, 0)])
    distance = 0
    
    visited = [[False] * n for _ in range(m)]
    visited[0][0] = True
    
    while 1:
        if len(queue) == 0: 
            break
            
        x, y = queue.popleft()
        
        if x == n-1 and y == m-1:
            check = 1
            break   
        
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            
            if nx >= n or ny >= m or nx < 0 or ny < 0:
                continue 
            
            if maps[nx][ny] == 0:
                continue
            
            if maps[nx][ny] == 1:
                queue.append([nx, ny])
                maps[nx][ny] = maps[x][y] +1
    
    answer = maps[n-1][m-1]
    if answer == 1:
        return -1
    return answer

 

 

시간/공간 복잡도

 

 

O(N*M)

 

최적화 및 개선

 

 

.

 

어려웠던 점

 

 

가로 세로가 헷깔렸음.

예전에 풀어봤던 문제인데도 처음엔 느낌조차 없다가 점점 느낌 살아났지만, 예전에 고민했던 부분을 또 고민하며 문제를 풀었다. 

'CodingTest > 문제 풀이 - Python' 카테고리의 다른 글

[프로그래머스 lv3] 배달  (1) 2024.04.10
[프로그래머스 lv3] 네트워크  (0) 2024.04.10
벨만포드 알고리즘  (0) 2024.04.09
다익스트라 알고리즘  (0) 2024.04.08
BFS 순회  (0) 2024.04.08

주석 있는 코드 

def solution(graph, source):
    # 1. 그래프의 노드 수
    num_vertices = len(graph)
    # 2. 거리 배열 초기화 
    distance = [float("inf")] * num_vertices
    distance [source] = 0
    # 3. 직전 경로 배열 초기화 
    predecessor = [None] * num_vertices

    # 4. 간선 수 만큼 반복하여 최단 경로 갱신
    for temp in range(num_vertices - 1):
        for u in range(num_vertices):
            for v, weight in graph[u]:
                # 5. 현재 노드 u를 거쳐서 노드 v로 가는 경로의 거리가 기존에 저장된 노드 v까지의
                # 거리보다 짧은 경우
                if distance[u] + weight < distance[v]:
                    # 6. 최단 거리를 갱신해줌.
                    distance[v] = distance[u] + weight
                    # 7. 직전 경로를 업데이트해줌.
                    predecessor[v] = u

    # 8. 음의 가중치 순회 체크 
    for u in range(num_vertices):
        for v, weight in graph[u]:
            # 9. 현재 노드 u를 거쳐서 노드 v로 가는 경로의 거리가 기존에 
            # 저장된 노드 v까지의 거리보다 짧은 경우
            if distance[u] + weight < distance[v]:
                # 10. 음의 가중치 순회가 발견됐음, [-1] 반환
                return [-1]

    return [distance, predecessor]

 

 

주석 간소화 코드

def solution(graph, source):
    vLen = len(graph)
    distances = [float("inf")] * vLen
    distances[source] = 0 # 최단거리 리스트, 시작은 0
    predecessor = [None] * vLen # 직전 노드 
    print("")

    # 일단 최단거리 그거 구해야함. 
    for i in range(0, vLen-1): # n-1번 반복함
        for v, node in enumerate(graph):
            for oneNode in node:
                currNode, weight = oneNode
                distance = distances[v] + weight
                if distance < distances[currNode]:
                    distances[currNode] = distance
                    predecessor[currNode] = v

    # 음의 순환 잡기 
    for v, node in enumerate(graph):
        for oneNode in node:
            currNode, weight = oneNode       
            distance = distances[v] + weight
            if distance < distances[currNode]:
                return [-1]

    return [distances, predecessor]

 

 

 

'CodingTest > 문제 풀이 - Python' 카테고리의 다른 글

[프로그래머스 lv3] 네트워크  (0) 2024.04.10
[프로그래머스 lv2] 게임 맵 최단거리  (0) 2024.04.09
다익스트라 알고리즘  (0) 2024.04.08
BFS 순회  (0) 2024.04.08
DFS 순회  (0) 2024.04.06
import heapq

def solution(graph, start):

# 1. 시작 노드 설정, 시작 노드부터 특정 노드까지 최소 비용을 저장할 공간과 직전 노드를 저장할 공간 마련
# 1-1. 최소 비용을 저장할 공간은 모두 매우 큰 값으로 초기화
# 무한대 약자는 INF 로 표현, 직전 노드를 저장할 공간 또한 INF로 초기화 
# 1-2. 시작 노드의 최소 비용은 0, 직전 노드는 자신으로

# 2. 해당 노드를 ㅌ오해 방문할 수 있는 노드 중, 아직 방문하자ㅣ 않는 노드 중 현재까지 구한 최소 비용이 
# 가장 작은 노드를 선택
# 2-1. 해당 노드를 거쳐 각 노드까지 가는 최소 비용과 현재까지 구한 최소 비용을 비교해 작은 값을
# 각 노드의 최소 비용으로 갱신함
# 2-2. 이때 직전 노드도 같이 갱신함.
# 3. 노드 개수에서 1을 뺀 만큼 반복함.
    
    distances = {node: float("inf") for node in graph}
    # 1. 모든 노드의 거리 값을 무한대로 초기화 
    # print(distances)

    distances[start] = 0 
    # 2. 시작 노드의 거리 값은 0으로 초기화 

    queue = []
    heapq.heappush(queue, [distances[start], start]) 
    # print('queue', queue) # [[0, 'A']]

    # 3. 시작 노드를 큐에 삽입
    paths = {start: [start]} # paths:  {'A': ['A']} 이렇게 나오는게 맞나,,? 
    # 4. 시작 노드의 경로를 초기화 

    # print('paths: ', paths)

    while queue:
        # 5. 현재 가장 거리 값이 작은 노드를 가져옴
        current_distance, current_node = heapq.heappop(queue)
        # 6. 만약 현재 노드의 거리 값이 큐에서 가져온 거리 값보다 크면,
        # 해당 노드는 이미 처리한 것이므로 무시

        if distances[current_node] < current_distance:
            continue

        # 7. 현재 노드와 인접한 노드들의 거리 값을 계산하여 업데이트
        
        for adjacent_node, weight in graph[current_node].items():
            distance = current_distance + weight
            # 8. 현재 계산한 거리 값이 기존 거리 값보다 작으면 최소 비용 및
            # 최단 경로 업데이트 
             
            if distance < distances[adjacent_node]:
                distances[adjacent_node] = distance # 최소 비용 업데이트
                paths[adjacent_node] = paths[current_node] + [adjacent_node]
                # 최단 경로 업데이트

                # 9. 최소 경로가 갱신된 노드를 비용과 함께 큐에 푸시
                heapq.heappush(queue, [distance, adjacent_node])

    # 10. paths 딕셔너리를 노드 번호에 따라 오름차순 정렬하여 반환
    sorted_paths = {node: paths[node] for node in sorted(paths)}

    return [distances, sorted_paths]

 

 

주석 없는 버전 

 

import heapq
def solution(graph, start):

    distances = {node: float("inf") for node in graph}
    distances[start] = 0

    queue = []
    heapq.heappush(queue, [distances[start], start])
    paths = {start: [start]}

    while queue:
        currDis, currNode = heapq.heappop(queue)

        if distances[currNode] < currDis:
            continue 

        for injeop, weight in graph[currNode].items():
            distance = currDis + weight
            if distances[currNode] > distance:
                distances[currNode] = distance
                paths[injeop] = paths[currNode] + [injeop]
                heapq.heappush(queue, [distance, injeop])

        
        sorted_paths = {node: paths[node] for node in sorted(paths)}


            
   
    return [distances, sorted_paths]

'CodingTest > 문제 풀이 - Python' 카테고리의 다른 글

[프로그래머스 lv2] 게임 맵 최단거리  (0) 2024.04.09
벨만포드 알고리즘  (0) 2024.04.09
BFS 순회  (0) 2024.04.08
DFS 순회  (0) 2024.04.06
[프로그래머스 lv2]전화번호 목록.ver2  (0) 2024.04.05
from collections import defaultdict, deque

def solution(graph, start):
    # 트리 생성 
    tmp_tree = defaultdict(list)
    for i, v in graph:
        tmp_tree[i].append(v)

    print(tmp_tree)
    
    def dfs(start):
        visited = set()
        queue = deque([start])
        visited.add(start)
        result.append(start)

        while queue:       
            node = queue.popleft() # 순차적으로 처리함 
            for injeop in tmp_tree.get(node, []):
                print('node', node, 'injeop', injeop)
                if injeop not in visited:
                    queue.append(injeop)
                    visited.add(injeop)
                    result.append(injeop)

    result = []
    dfs(start)  
    return result

'CodingTest > 문제 풀이 - Python' 카테고리의 다른 글

벨만포드 알고리즘  (0) 2024.04.09
다익스트라 알고리즘  (0) 2024.04.08
DFS 순회  (0) 2024.04.06
[프로그래머스 lv2]전화번호 목록.ver2  (0) 2024.04.05
[프로그래머스 lv2]영어 끝말잇기.ver2  (0) 2024.04.05

 

from collections import defaultdict

def solution(graph, start):

    adj_list = defaultdict(list)
    for u, v in graph:
        adj_list[u].append(v)


    def dfs(node, visited, result):
        visited.add(node)
        result.append(node)
        for neighbor in adj_list.get(node, []):
            print('neighbor', neighbor)

            if neighbor not in visited:
                dfs(neighbor, visited, result)

    
    visited=set()
    result = []
    dfs(start, visited, result)

    return result

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

문제설명

 

 

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.

전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.

 

구조대 : 119

박준영 : 97 674 223

지영석 : 11 9552 4421

전화번호부에 적힌 전화번호를 담은 배열 phone_book  solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true return 하도록 solution 함수를 작성해주세요.

 

 

제한 사항

 

 

phone_book의 길이는 1 이상 1,000,000 이하입니다.

각 전화번호의 길이는 1 이상 20 이하입니다.

같은 전화번호가 중복해서 들어있지 않습니다.

 

 

입출력 예제

 

 

phone_book       return
["119", "97674223", "1195524421"]   false
["123","456","789"]  true
["12","123","1235","567","88"] false

 

 

 

입출력 예 설명

 

 

입출력 예 #1

앞에서 설명한 예와 같습니다.

 

입출력 예 #2

한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.

 

입출력 예 #3

첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.

 

 

문제 해결 방법

 

그래서 연속된 두 문자씩 비교함

 

코드 구현

 

 

def solution(phone_book):
    answer = True
    phone_book.sort()

    count=0
    for num in phone_book:
        if count==0:
            count+=1
            pass
        else:
            preNum = phone_book[count-1]
            if preNum in num and num.startswith(preNum):
                answer = False
            count+=1
    
    return answer

 

 

 

시간/공간 복잡도

 

 

O(N)

 

 

최적화 및 개선

 

그래서 연속된 두 문자씩 비교를 위해 문자열 상태에서 sort를 하여 찾는 효율을 높임.

시간 초과 개선을 위해 모든 문자열 비교하려고 하지않음.

특정 문자열이 문자열 접두사로 붙는 것을 확인하기 위해 startswith함수를 사용함.

 

 

어려웠던 점 및 느낀점

 

없음. 확실히 예전에 푼문제라 그런가 이해가 빨리되고, 풀때 헤메는 것도 잠깐이고 코드가 간결해짐.

 

 

 

 

 

 

 

'CodingTest > 문제 풀이 - Python' 카테고리의 다른 글

BFS 순회  (0) 2024.04.08
DFS 순회  (0) 2024.04.06
[프로그래머스 lv2]영어 끝말잇기.ver2  (0) 2024.04.05
[프로그래머스 lv3]길 찾기 게임  (0) 2024.04.04
[프로그래머스 lv3]미로 탈출  (0) 2024.03.20

https://school.programmers.co.kr/learn/courses/30/lessons/12981?language=python3

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제설명

 

1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.

1번부터 번호 순서대로  사람씩 차례대로 단어를 말합니다.

마지막 사람이 단어를 말한 다음에는 다시 1번부터 시작합니다.

앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야 합니다.

이전에 등장했던 단어는 사용할  없습니다.

 글자인 단어는 인정되지 않습니다.

다음은 3명이 끝말잇기를 하는 상황을 나타냅니다.

tank  kick  know  wheel  land  dream  mother  robot  tank

 끝말잇기는 다음과 같이 진행됩니다.

1 사람이 자신의  번째 차례에 tank 말합니다.

2 사람이 자신의  번째 차례에 kick 말합니다.

3 사람이 자신의  번째 차례에 know 말합니다.

1 사람이 자신의  번째 차례에 wheel 말합니다.

(계속 진행)

끝말잇기를 계속 진행해 나가다 보면, 3 사람이 자신의  번째 차례에 말한 tank 라는 단어는 이전에 등장했던 단어이므로 탈락하게 됩니다.

사람의  n 사람들이 순서대로 말한 단어 words  매개변수로 주어질 , 가장 먼저 탈락하는 사람의 번호와  사람이 자신의  번째 차례에 탈락하는지를 구해서 return 하도록 solution 함수를 완성해주세요.

제한 사항

끝말잇기에 참여하는 사람의  n 2 이상 10 이하의 자연수입니다.

words 끝말잇기에 사용한 단어들이 순서대로 들어있는 배열이며, 길이는 n 이상 100 이하입니다.

단어의 길이는 2 이상 50 이하입니다.

모든 단어는 알파벳 소문자로만 이루어져 있습니다.

끝말잇기에 사용되는 단어의 (의미) 신경 쓰지 않으셔도 됩니다.

정답은 [ 번호, 차례 ] 형태로 return 해주세요.

만약 주어진 단어들로 탈락자가 생기지 않는다면, [0, 0] return 해주세요.

문제 해결 방법

문제를 풀기위한 조건들을 하나하나 생각해서 하나하나 제외해가면서 풀었음

 

코드 구현

def solution(n, words):
    answer = []
    # 1번부터 마지막 순서까지 돌고돈다.
    # 앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야한다. 
    # 이전에 등장했던 단어는 사용할 수 없다. 
    # 한 글자 단어 인정안해줌
    newWords=[] #스택에 쌓음
    newWords.append(words[0]) 
    
    cnt = 1 #words에서 어디를 가리키는지 
    big_phase=0
    check = 0
    check2 = 0
    while 1:
        big_phase+=1
        for i in range(1, n+1):
            if check ==1:
                answer.append(i)
                answer.append(big_phase)
                return answer
            
            if check2 == 1:
                answer.append(i)
                answer.append(big_phase)
                return answer
            
            if cnt == len(words):
                break
            
            if words[cnt][0] == newWords[-1][-1]:
                pass
            else:
                check = 1
                
            
            if words[cnt] in newWords:
                check2 = 1
            else:
                newWords.append(words[cnt])  
                cnt+=1
                
        if cnt == len(words):
                break

    answer.append(0)
    answer.append(0)
    
    return answer

 

시간/공간 복잡도

O(n)

 

최적화 및 개선

최적화 및 개선하지 않음

 

어려웠던 점

 

예전에 작성한 코드랑 그닥 로직이 다른거 같진 않다.. 

스스로 더 로직을 잘 이해하고 풀었다는 차이점이 존재할뿐? 

 

 

 

+ Recent posts