728x90
반응형
    • 올바른 괄호

darklight

sublimevimemacs

Python3 

문제 설명

괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어

  • ()() 또는 (())() 는 올바른 괄호입니다.
  • )()( 또는 (()( 는 올바르지 않은 괄호입니다.

'(' 또는 ')' 로만 이루어진 문자열 s가 주어졌을 때, 문자열 s가 올바른 괄호이면 true를 return 하고, 올바르지 않은 괄호이면 false를 return 하는 solution 함수를 완성해 주세요.

제한사항

  • 문자열 s의 길이 : 100,000 이하의 자연수
  • 문자열 s는 '(' 또는 ')' 로만 이루어져 있습니다.

입출력 예

sanswer

()() true
(())() true
)()( false
(()( false

입출력 예 설명

입출력 예 #1,2,3,4
문제의 예시와 같습니다

 

 

1차 : 실패한 풀이

def solution(s):
    answer = True
    while True:
        temp = s.replace('()','')
        if s == temp:
            break
        s = temp
    if not s:
        return True
    else: return False

결과는 테스트케이스에서 기대한 값과 같게 나왔지만 시간초과의 이유로 효율성 점수가 낮게 나왔다.

백준에서도 괄호의 완전성을 따지는 비슷한 문제가 있었는데,

그 때도 완전한 괄호를 replace로 바꾸면서 반복했을 때 시간초과가 났던 기억이 있어 다른 방법을 생각했다.

 

2차: 성공

def solution(s):
    t = []
    for i in s:
        if i=="(":
            t.append(i)
        else:
            if t:
                t.pop()
            else: return False
    if t: return False
    else: return True

스택으로 풀면 해결할 수 있다.

728x90
반응형
728x90
반응형

문제 설명

오픈채팅방

카카오톡 오픈채팅방에서는 친구가 아닌 사람들과 대화를 할 수 있는데, 본래 닉네임이 아닌 가상의 닉네임을 사용하여 채팅방에 들어갈 수 있다.

신입사원인 김크루는 카카오톡 오픈 채팅방을 개설한 사람을 위해, 다양한 사람들이 들어오고, 나가는 것을 지켜볼 수 있는 관리자창을 만들기로 했다. 채팅방에 누군가 들어오면 다음 메시지가 출력된다.

[닉네임]님이 들어왔습니다.

채팅방에서 누군가 나가면 다음 메시지가 출력된다.

[닉네임]님이 나갔습니다.

채팅방에서 닉네임을 변경하는 방법은 다음과 같이 두 가지이다.

  • 채팅방을 나간 후, 새로운 닉네임으로 다시 들어간다.
  • 채팅방에서 닉네임을 변경한다.

닉네임을 변경할 때는 기존에 채팅방에 출력되어 있던 메시지의 닉네임도 전부 변경된다.

예를 들어, 채팅방에 Muzi와 Prodo라는 닉네임을 사용하는 사람이 순서대로 들어오면 채팅방에는 다음과 같이 메시지가 출력된다.

Muzi님이 들어왔습니다.
Prodo님이 들어왔습니다.

채팅방에 있던 사람이 나가면 채팅방에는 다음과 같이 메시지가 남는다.

Muzi님이 들어왔습니다.
Prodo님이 들어왔습니다.
Muzi님이 나갔습니다.

Muzi가 나간후 다시 들어올 때, Prodo 라는 닉네임으로 들어올 경우 기존에 채팅방에 남아있던 Muzi도 Prodo로 다음과 같이 변경된다.

Prodo님이 들어왔습니다.
Prodo님이 들어왔습니다.
Prodo님이 나갔습니다.
Prodo님이 들어왔습니다.

채팅방은 중복 닉네임을 허용하기 때문에, 현재 채팅방에는 Prodo라는 닉네임을 사용하는 사람이 두 명이 있다. 이제, 채팅방에 두 번째로 들어왔던 Prodo가 Ryan으로 닉네임을 변경하면 채팅방 메시지는 다음과 같이 변경된다.

Prodo님이 들어왔습니다.
Ryan님이 들어왔습니다.
Prodo님이 나갔습니다.
Prodo님이 들어왔습니다.

채팅방에 들어오고 나가거나, 닉네임을 변경한 기록이 담긴 문자열 배열 record가 매개변수로 주어질 때, 모든 기록이 처리된 후, 최종적으로 방을 개설한 사람이 보게 되는 메시지를 문자열 배열 형태로 return 하도록 solution 함수를 완성하라.

제한사항

  • record는 다음과 같은 문자열이 담긴 배열이며, 길이는 1 이상 100,000 이하이다.
  • 다음은 record에 담긴 문자열에 대한 설명이다.
    • 모든 유저는 [유저 아이디]로 구분한다.
    • [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - Enter [유저 아이디] [닉네임] (ex. Enter uid1234 Muzi)
    • [유저 아이디] 사용자가 채팅방에서 퇴장 - Leave [유저 아이디] (ex. Leave uid1234)
    • [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - Change [유저 아이디] [닉네임] (ex. Change uid1234 Muzi)
    • 첫 단어는 Enter, Leave, Change 중 하나이다.
    • 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다.
    • 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다.
    • 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다.
    • 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다.

입출력 예

recordresult

["Enter uid1234 Muzi", "Enter uid4567 Prodo","Leave uid1234","Enter uid1234 Prodo","Change uid4567 Ryan"] ["Prodo님이 들어왔습니다.", "Ryan님이 들어왔습니다.", "Prodo님이 나갔습니다.", "Prodo님이 들어왔습니다."]

입출력 예 설명

입출력 예 #1
문제의 설명과 같다.

 

 

def solution(record):
    answer = []
    d = {}
    for i in range(len(record)):
        record[i] = record[i].split()
    for i in range(len(record)):
        if record[i][0] == 'Enter':
            answer.append([record[i][1], '님이 들어왔습니다.'])
            d[record[i][1]] = record[i][2]
        elif record[i][0] == 'Leave':
            answer.append([record[i][1], '님이 나갔습니다.'])
        elif record[i][0] == 'Change':
            d[record[i][1]] = record[i][2]
    for i in range(len(answer)):
        answer[i][0] = d[answer[i][0]]
        answer[i] = ''.join(answer[i])
    return answer

 

유저ID와 닉네임을 연동할 필요성이 있음을 느껴 딕셔너리를 이용했다.

answer 리스트 안에 1차적으로 user id를 저장해두고

Enter 나 Change를 통해 닉네임이 변경된 것이 있다면 변경사항이 적용되도록 했다.

split으로 분리해놓은 문자열 배열을 ''.join을 통해 다시 합쳤다.

728x90
반응형
728x90
반응형

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

 

1699번: 제곱수의 합

어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다

www.acmicpc.net

 

x = int(input()) 
dp = [0] * (x+1) 
for i in range(1, x+1): 
    dp[i] = i 
    for j in range(1, i): 
        if (j * j) > i: 
            break 
        dp[i] = min(dp[i], dp[i - j**2] + 1) 

print(dp[x])

 

python으로 제출하면 시간초과가 난다. pypy3으로 제출했다.

32, 64, 128 등의 반례를 찾았기 때문에

가까운 제곱수 항 개수를 생각하는 것이 아니라

여태까지 나온 모든 제곱수 항을 확인해봐야한다는 것에 착안해야한다.

 

728x90
반응형
728x90
반응형

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

 

1753번: 최단경로

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다.

www.acmicpc.net

import heapq
import sys

n, e = map(int, sys.stdin.readline().split())
s = int(input())
a = [[]for _ in range(n+1)]
for _ in range(e):
    u, v, w = map(int, sys.stdin.readline().split())
    a[u].append((w, v))
INF = 10 * n + 1
d = [INF] * (n+1)
d[s] = 0
queue = []
heapq.heappush(queue, (0,s))
while queue:
    cost, now = heapq.heappop(queue)

    for x, next_node in a[now]:
        xc = x + cost
        if xc < d[next_node]:
            d[next_node] = xc
            heapq.heappush(queue, (xc, next_node))

for i in range(1, n+1):
    if d[i]==INF:
        print('INF')
    else: print(d[i])

 

다익스트라 알고리즘을 처음 익히기에 좋은 문제였다. 

경로 가중치의 조건이 10 이하의 자연수라는 점에서 INF를 10*n + 1 로 설정해서 수월하게 풀 수 있었다. 

 

다익스트라 알고리즘을 구현할 때 힙 구조를 많이 사용한다고 하여 힙 구조에 대해 복습했다.

힙 구조 안에 리스트를 넣는 방법으로 삼중 리스트로 해결해도 되지만 개인적으로 편한 튜플로 해결했다.

참조 : https://sungmin-joo.tistory.com/33

https://hsp1116.tistory.com/42

728x90
반응형
728x90
반응형

www.acmicpc.net/problem/2193

 

2193번: 이친수

0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다. 이친수는 0으로 시작하지 않

www.acmicpc.net

 

n = int(input())
dp = [0,1,1]
for i in range(3,n+1):
    dp.append(dp[i-1]+dp[i-2])
print(dp[-1])

 

몇 개씩 나오는지 케이스를 나열해봤더니

1,1,2,3,5,8,13,21 ... 의 형태로 나와서 바로 풀 수 있었다.

728x90
반응형

+ Recent posts