728x90
반응형

문제

https://www.acmicpc.net/problem/2606

 

 

풀이 (bfs)

from collections import deque

# 1. 입력받기
n=int(input()) # 컴퓨터 개수
v=int(input()) # 연결선 개수
graph = [[] for i in range(n+1)] # 그래프 초기화

for i in range(v): # 그래프 생성
    a,b=map(int,input().split())
    graph[a]+=[b] # a에 b 연결
    graph[b]+=[a] # b에 a 연결 -> 양방향
    
#print(graph)

# 2. 노드 탐색 (bfs / 큐)
visited = [0] * (n+1) # 방문 여부 체크
visited[1]=1 # 1번 컴퓨터부터 시작이니 방문 표시
Q=deque([1])
while Q:
    c=Q.popleft() # 왼쪽에서 빼기
    for nx in graph[c]:
        if visited[nx]==0:
            Q.append(nx) #오른쪽에 추가
            visited[nx]=1

print(sum(visited)-1)

 

 

풀이 (dfs)

# 1. 입력받기
n = int(input())
v = int(input())
graph = [[] for i in range(n+1)] # 그래프 초기화

for i in range(v):
    a,b = map(int, input().split())
    graph[a] += [b]
    graph[b] += [a]

#print(graph)

visited = [0] * (n+1)

# 2. dfs 함수 구현 (재귀)
def dfs(v):
    visited[v]=1

    for nx in graph[v]:
        if visited[nx]==0:
            dfs(nx)
        #print(f"v={v} | nx={nx} | {visited}")

# 3. 노드 탐색 (dfs / 재귀)
dfs(1)
#print(visited)
print(sum(visited) -1)

 

 

출처

https://bio-info.tistory.com/152

 

[백준] 2606 바이러스 - Python (그래프 탐색)

Contents 1. 문제 정의 및 예제 해석 (문제 링크: https://www.acmicpc.net/problem/2606) 2606번: 바이러스 첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번

bio-info.tistory.com

 

 

728x90
반응형
728x90
반응형

문제

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

 

프로그래머스

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

programmers.co.kr

 

 

풀이

[개요]

1. 오른쪽으로 돌다가 끝에 다다르면 아래쪽으로 방향 바꾸기

2. 아래쪽으로 돌다가 끝에 다다르면 왼쪽으로 방향 바꾸기

3. 왼쪽으로 돌다가 끝에 다다르면 위쪽으로 방향 바꾸기

 

[이슈]

끝을 어떻게 판단할 수 있을까?

1. 다음 좌표의 값이 0이 아니어야 함

2. 다음 좌표가 0보다 작거나, n보다 크거나 같으면 끝임

 

[파이썬문법]

1. 리스트 0으로 초기화 : answer = [[0 for i in range(n)] for j in range(n)]

 

 

정답코드

def solution(n):
    answer = [[]]
    answer = [[0 for i in range(n)] for j in range(n)]
    val = 0
    
    #우 하 좌 상
    d = 0
    dx = [0, 1,  0, -1] #행 
    dy = [1, 0, -1,  0] #열
    
    #현재 좌표
    cur = [0,0]
    
    while val < n*n:
        #현재좌표 값 채우기
        val += 1
        answer[cur[0]][cur[1]] = val
        
        #다음 좌표
        x = cur[0] + dx[d]
        y = cur[1] + dy[d]
        next = [x, y]
        #print(f"next={next}")
        
        #다음좌표값이 0보다 크면 방향 바꾸기
        #다음좌표가 맨끝이면 방향바꾸기 
        if (x>n-1 or x<0 or y>n-1 or y<0) or answer[next[0]][next[1]] > 0:
            if d < 3:
                d += 1
            else:
                d = 0
        
        #print(f"d={d}")
        
        #현재좌표를 다음 좌표로 바꾸기
        x = cur[0] + dx[d]
        y = cur[1] + dy[d]
        next = [x, y]
        cur = next
        
        #print(answer)
    
    return answer

 

728x90
반응형

'알고리즘' 카테고리의 다른 글

[백준] 2606 - 바이러스 (python3)  (0) 2024.05.10
[프로그래머스] 옹알이(1)  (0) 2024.03.25
[프로그래머스] 타겟넘버  (0) 2024.01.05
[파이썬] 괄호 짝 확인하기  (0) 2023.12.15
[파이썬] 런던 폭우 Ⅱ  (0) 2023.09.30
728x90
반응형

문제

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

정답

def solution(babbling):
    answer = 0
    
    arr = ["aya", "ye", "woo", "ma" ]
    
    for x in babbling:
        for y in arr:
            x = x.replace(y, ' ')
            if x.strip() == "":
                answer += 1
                break;
        
    return answer

풀이

  • 같은 문자열을 찾으면 ""이 아니라 " "로 replace한다!
    • 케이스) "wyeoo" 
      • x.replace(y, "")  : "wyeoo" ➡️ "woo" ➡️ ""
      • x.replace(y, " ") : "wyeoo" ➡️ "w  oo" ➡️ "w oo"
728x90
반응형
728x90
반응형

문제


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



문제유형 : BFS, DFS


BFS 풀이법


def solution(numbers, target):
    answer = bfs(numbers, target)
    return answer

def bfs(numbers, target):
    answer = 0
    sums = [0] 
    
    for num in numbers:
        tmp = []
        for s in sums:
            tmp.append(s + num)
            tmp.append(s - num)
        sums = tmp
        
    for s in sums:
        if s == target:
            answer += 1
    
    return answer
  •  `sums = []`, `tmp = [0]` 로 초기화했다가 에러가 발생했다.
  • `for s in sums` 에서 빈 배열에 접근하므로 인덱스 에러가 발생했을 것이다



DFS 풀이법


def solution(numbers, target):
    answer = dfs(numbers, target, 0)
    return answer

def dfs(numbers, target, depth):
    answer = 0
    # 탈출조건
    if len(numbers) == depth:
        if sum(numbers) == target:
            return 1
        else:
            return 0
    else:
        answer += dfs(numbers, target, depth+1)
        numbers[depth] *= -1
        answer += dfs(numbers, target, depth+1)
        return answer
        
        def solution(numbers, target):

 

다시 한 번 풀어봄

def solution(numbers, target):
    answer = 0
    answer = dfs(numbers, target, 0, 0)
    return answer

def dfs(numbers, target, depth, sum):
    cnt = 0
    
    if depth == len(numbers):
        if sum == target:
            #print("탈출=[1]-----------------------")
            return 1
        else:
            #print("탈출=[0]-----------------------")
            return 0
    else:
        a, b = numbers[depth], (numbers[depth]*-1)
        #print(f"depth={depth} | sum={sum} | a,b={a,b} | cnt={cnt}")
        
        cnt += dfs(numbers, target, depth+1, sum+a)
        #print(f"depth={depth} | sum={sum} | a={a} | cnt={cnt}")
        
        cnt += dfs(numbers, target, depth+1, sum+b)
        #print(f"depth={depth} | sum={sum} | b={b} | cnt={cnt}")
        
        #print(f"재귀 out | cnt={cnt}")
        return cnt
728x90
반응형
728x90
반응형
from collections import deque

def parentheses_checker(string):
    """주어진 문자열 인풋의 모든 괄호가 짝이 있는지 확인해주는 메소드"""

    stack = deque()  # 사용할 스택 정의

    print(f"테스트하는 문자열: {string}") 

    # 문자열의 각 문자를 돌면서
    for i in range(len(string)):
        # 열리는 괄호가 있는 위치를 스택에 저장한다
        if string[i] == "(":
            stack.append(i)
        # 닫히는 괄호가 있으면
        elif string[i] == ")":
            # 스택에 열린 괄호 위치 데이터가 있으면 삭제하고
            if stack:
                stack.pop()
            # 아니면 현재 위치에 있는 닫는 괄호에 맞는 열리는 괄호가 없다고 출력한
            else:
                print(f"문자열 {i} 번째 위치에 있는 닫는 괄호에 맞는 열리는 괄호가 없습니다")

    # 스택에 열린 괄호 위치 데이터가 남아 있으면 해당 열린 괄호는 짝이 맞는 닫힌 괄호가 없다는 뜻이다
    while stack:
        print(f"문자열 {stack.pop()} 번째 위치에 있는 괄호가 닫히지 않았습니다")

case1 = "(1+2)*(3+5)"
case2 = "((3*12)/(41-31))"
case3 = "((1+4)-(3*12)/3"
case4 = "(12-3)*(56/3))"
case5 = ")1+14)/3"
case6 = "(3+15(*3"

parentheses_checker(case1)
parentheses_checker(case2)
parentheses_checker(case3)
parentheses_checker(case4)
parentheses_checker(case5)
parentheses_checker(case6)
728x90
반응형

'알고리즘' 카테고리의 다른 글

[프로그래머스] 옹알이(1)  (0) 2024.03.25
[프로그래머스] 타겟넘버  (0) 2024.01.05
[파이썬] 런던 폭우 Ⅱ  (0) 2023.09.30
[파이썬] 리스트 항목 합 탐색  (0) 2023.09.30
[파이썬] 중복되는 항목 찾기 Ⅱ  (0) 2023.09.30
728x90
반응형

실습 설명

런던에 엄청난 폭우가 쏟아진다고 가정합시다. 정말 재난 영화에서나 나올 법한 양의 비가 내려서, 고층 건물이 비에 잠길 정도입니다.

그렇게 되었을 때, 건물과 건물 사이에 얼마큼의 빗물이 담길 수 있는지 알고 싶은데요. 그것을 계산해 주는 함수 trapping_rain()을 작성해 보려고 합니다.

함수 trapping_rain()은 건물 높이 정보를 보관하는 리스트 buildings를 파라미터로 받고, 담기는 빗물의 총량을 리턴해 줍니다.

예를 들어서 파라미터 buildings로 [3, 0, 0, 2, 0, 4]가 들어왔다고 합시다. 그러면 0번 인덱스에 높이 3의 건물이, 3번 인덱스에 높이 2의 건물이, 5번 인덱스에 높이 4의 건물이 있다는 뜻입니다. 1번, 2번, 4번 인덱스에는 건물이 없습니다.

그러면 아래의 사진에 따라 총 10 만큼의 빗물이 담길 수 있습니다. 따라서 trapping_rain() 함수는 10을 리턴하는 거죠.



3차원 말고, 2차원으로 생각해 주세요!
이번에는 파라미터 buildings로 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]가 들어왔다고 합시다. 그러면 아래의 사진에 따라 총 6 만큼의 빗물이 담길 수 있습니다. 따라서 trapping_rain() 함수는 6을 리턴하는 거죠.

  • 리스트 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]

이 정보를 기반으로, trapping_rain() 함수를 작성해 보세요!

더 많은 공간을 쓰더라도 조금 더 효율적인 시간 복잡도로 문제를 풀어 볼까요?

실습 결과

def trapping_rain(buildings):
    total_height = 0 # 총 갇히는 비의 양을 담을 변수
    n = len(buildings)

    # 각각 왼쪽 오른쪽 최대값 리스트 정의
    left_list = [0] * n
    right_list = [0] * n

    # buildings 리스트 각 인덱스 별로 왼쪽으로의 최댓값을 저장한다
    left_list[0] = buildings[0]
    for i in range(1, n):
        left_list[i] = max(left_list[i-1], buildings[i-1])
                
    # buildings 리스트 각 인덱스 별로 오른쪽으로의 최댓값을 저장한다
    right_list[-1] = buildings[-1]
    for i in range(n - 2, -1, -1):
        right_list[i] = max(right_list[i+1], buildings[i+1])

    # 저장한 값들을 이용해서 총 갇히는 비의 양을 계산한다
    for i in range(1, n-1):
        # 현재 인덱스에 빗물이 담길 수 있는 높이
        upper_bound = min(right_list[i], left_list[i])

        # 현재 인덱스에 담기는 빗물의 양을 계산
        # 만약 upper_bound가 현재 인덱스 건물보다 높지 않다면, 현재 인덱스에 담기는 빗물은 0
        total_height += max(0, upper_bound - buildings[i])

    return total_height


print(trapping_rain([3, 0, 0, 2, 0, 4]))
print(trapping_rain([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]))
10
6

시간 복잡도

공간 복잡도

728x90
반응형
728x90
반응형

실습 설명

[1, 2, 5, 6, 7, 9, 11] 안에 합이 15가 되는 두 요소의 조합이 있는지 확인하고 싶습니다. 두 요소 6과 9의 합이 15가 되죠? 이 조합이 있는지 없는지를 알고 싶은 거죠.

함수 설명

함수 sum_in_list()는 정수 search_sum과 정렬된 정수 리스트 sorted_list를 받아서 sorted_list안의 두 요소의 합이search_sum이 되는 조합이 있는지 없는지를 불린으로 리턴합니다.

sum_in_list(15, [1, 2, 5, 6, 7, 9, 11])은 불린 True를 리턴합니다.

실습 결과

def sum_in_list(search_sum, sorted_list):
    low = 0
    high = len(sorted_list) - 1
    
    while low < high:
        candidate_sum = sorted_list[low] + sorted_list[high]
        
        if candidate_sum == search_sum: # 합이 찾으려는 숫자일 때
            return True
        
        if candidate_sum < search_sum:  # 합이 찾으려는 숫자보다 작을 때
            low += 1
        
        else: # 합이 찾으려는 숫자보다 클 때
            high -= 1
    
    # 찾는 조합이 없기 때문에 False 리턴
    return False
    
# 테스트 코드
print(sum_in_list(15, [1, 2, 5, 6, 7, 9, 11]))
print(sum_in_list(15, [1, 2, 5, 7, 9, 11]))
15
8
27

 

728x90
반응형

'알고리즘' 카테고리의 다른 글

[파이썬] 괄호 짝 확인하기  (0) 2023.12.15
[파이썬] 런던 폭우 Ⅱ  (0) 2023.09.30
[파이썬] 중복되는 항목 찾기 Ⅱ  (0) 2023.09.30
[파이썬] 출근하는 방법 Ⅱ  (0) 2023.09.30
[파이썬] 출근하는 방법 Ⅰ  (0) 2023.09.30
728x90
반응형

실습 설명

(N + 1)의 크기인 리스트에, 1부터 N까지의 임의의 자연수가 요소로 할당되어 있습니다. 그렇다면 어떤 수는 꼭 한 번은 반복되겠지요.

예를 들어 [1, 3, 4, 2, 5, 4]와 같은 리스트 있을 수도 있고, [1, 1, 1, 6, 2, 2, 3]과 같은 리스트가 있을 수도 있습니다. (몇 개의 수가 여러 번 중복되어 있을 수도 있습니다.)

이러한 리스트에서 반복되는 요소를 찾아내려고 합니다.

중복되는 어떠한 수 ‘하나’만 찾아내도 됩니다. 즉 [1, 1, 1, 6, 2, 2, 3]의 예시에서 1, 2를 모두 리턴하지 않고, 1 또는 2 하나만 리턴하게 하면 됩니다.

이번 과제에서는 두 가지의 제약이 있습니다.

  1. O(n)이상의 공간을 사용할 수 없습니다. 즉 사전이나 리스트와 같이 인풋 리스트의 길이에 비례하는 공간 저장 도구를 사용할 수 없습니다!
  2. 인풋으로 받는 리스트 some_list의 요소들을 바꾸거나 변형할 수 없습니다.

실습 결과

def find_same_number(some_list, start = 1, end = None):
    if end == None:
        end = len(some_list)

    # 반복 요소를 찾으면 리턴한다
    if start == end:
        return start

    # 중간 지점을 구한다
    mid = (start + end) // 2

    # 왼쪽 범위의 숫자를 센다. 오른쪽은 리스트 길이에서 왼쪽 길이를 빼면 되기 때문에 세지 않는다
    left_count = 0

    for element in some_list:
        if start <= element and element <= mid:
            left_count += 1

    # 왼쪽과 오른쪽 범위중 과반 수 이상의 숫자가 있는 범위 내에서 탐색을 다시한다
    if left_count > mid - start + 1:
        return find_same_number(some_list, start, mid)

    return find_same_number(some_list, mid + 1, end)

print(find_same_number([1, 4, 3, 5, 3, 2]))
print(find_same_number([4, 1, 5, 2, 3, 5]))
print(find_same_number([5, 2, 3, 4, 1, 6, 7, 8, 9, 3]))
3
5
3

시간 복잡도

728x90
반응형

'알고리즘' 카테고리의 다른 글

[파이썬] 런던 폭우 Ⅱ  (0) 2023.09.30
[파이썬] 리스트 항목 합 탐색  (0) 2023.09.30
[파이썬] 출근하는 방법 Ⅱ  (0) 2023.09.30
[파이썬] 출근하는 방법 Ⅰ  (0) 2023.09.30
[파이썬] 삼송전자 주식 분석  (0) 2023.09.30
728x90
반응형

실습 설명

영훈이는 출근할 때 계단을 통해 사무실로 가는데요. 급할 때는 두 계단씩 올라가고 여유 있을 때는 한 계단씩 올라갑니다. 결국 계단을 오를 수 있는 모든 방법으로 계단을 올라갔는데요.

이제 다르게 계단을 올라갈 수는 없을까 고민하던 영훈이는 특이한 방법으로 계단을 오르려고 합니다.

가령 계단을 한 번에 1, 2, 4 칸씩 올라가 보는 건데요. 예를 들어서 계단을 4개를 올라가야 되면:

  • 1, 1, 1, 1
  • 2, 1, 1
  • 1, 2, 1
  • 1, 1, 2
  • 2, 2
  • 4

총 6개 방법이 있네요.

함수 설명

함수 staircase()는 파라미터로 총 계단 수 n 그리고 한 번에 올라갈 수 있는 계단 수를 possible_steps로 받고, 올라갈 수 있는 방법의 수를 효율적으로 찾아서 리턴합니다.

그러니까 n이 3, possible_steps 가 [1, 2, 3]이면, 계단 총 3칸을 1, 2, 3칸씩 갈 수 있을 때 오르는 방법의 수를 구하는 거죠. 단, possible_steps에는 항상 1이 포함된다고 가정합니다.

 

실습 결과

# 높이 n개의 계단을 올라가는 방법을 리턴한다
def staircase(stairs, possible_steps):
    # 계단 높이가 0 이거나 1 이면 올라가는 방법은 한 가지밖에 없다
    number_of_ways = [1, 1]
    
    # 이 변수들을 업데이트해 주며 n 번째 계단을 오르는 방법의 수를 구한다.
    for height in range(2, stairs + 1):
        number_of_ways.append(0)

        for step in possible_steps:
            # 음수 계단 수는 존재하지 않기 때문에 무시합니다
            if height - step >= 0:
                number_of_ways[height] += number_of_ways[height - step]

    return number_of_ways[stairs]

print(staircase(5, [1, 2, 3]))
print(staircase(6, [1, 2, 3]))
print(staircase(7, [1, 2, 4]))
print(staircase(8, [1, 3, 5]))
13
24
31
19

시간 복잡도

728x90
반응형
728x90
반응형

실습 설명

영훈이는 출근할 때 계단을 통해 사무실로 가는데요. 급할 때는 두 계단씩 올라가고 여유 있을 때는 한 계단씩 올라 갑니다.

어느 날 문득, 호기심이 생겼습니다. 한 계단 또는 두 계단씩 올라가서 끝까지 올라가는 방법은 총 몇 가지가 있을까요?

계단 4개를 올라간다고 가정하면, 이런 방법들이 있습니다.

  • 1, 1, 1, 1
  • 2, 1, 1
  • 1, 2, 1
  • 1, 1, 2
  • 2, 2

총 5개 방법이 있네요.

함수 staircase()는 파라미터로 계단 수 n을 받고, 올라갈 수 있는 방법의 수를 효율적으로 찾아서 리턴합니다.

print(staircase(0))  # => 1
print(staircase(1))  # => 1
print(staircase(4))  # => 5

 

실습 결과

def staircase(n):
    a, b = 1, 1
    for i in range(n):
        a, b = b, a + b
    return a

# 테스트 코드
print(staircase(0))
print(staircase(6))
print(staircase(15))
print(staircase(25))
print(staircase(41))
1
13
987
121393
267914296

시간 복잡도

728x90
반응형

+ Recent posts