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

 

2609번: 최대공약수와 최소공배수

첫째 줄에는 입력으로 주어진 두 수의 최대공약수를, 둘째 줄에는 입력으로 주어진 두 수의 최소 공배수를 출력한다.

www.acmicpc.net

 

풀이 과정

최대공약수는 유클리드 호제법을 이용해서 구할 수 있다.

 

GCD(a, b)를 a, b의 최대공약수라고 하고 a % b = r 이라고 하면 GCD(a, b) = GCD(b, r)이 성립한다. 이 과정을 반복해서 GCD(c, 0)이 되면 c가 두 수 a, b의 최대공약수다.

 

ex) GCD(24, 16) = GCD(16, 8) = GCD(8, 0) => 24와 16의 최대공약수는 8

 

최소공배수 LCM은 a*b / GCD임이 알려져 있으니 이를 통해 구하면 된다.

 

ex) LCM(24, 16) = 24 * 16 / 8 = 48 => 24와 16의 최소공배수는 48

코드

import sys

def gcd(a, b):
    if b == 0: return a
    else: return gcd(b, a%b)

lcm = lambda a, b: a*b//gcd(a, b)


a, b = map(int, input().split())
print(gcd(a, b))
print(lcm(a, b))

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

 

10430번: 나머지

첫째 줄에 A, B, C가 순서대로 주어진다. (2 ≤ A, B, C ≤ 10000)

www.acmicpc.net

 

풀이 과정

(A+B) mod M = ((A mod M) + (B mod M)) mod M

(AxB) mod M = ((A mod M) x (B mod M)) mod M

(A-B) mod M = ((A mod M) - (B mod M) + M) mod M은 모두 성립한다.

 

따라서 문제에서 물어보는 것은 모두 같다가 정답이고 실제로 출력해보면 실제로 같게 나온다.

코드

import sys

A, B, C = map(int, input().split())

print((A+B)%C)
print((A+B)%C)
print((A*B)%C)
print((A*B)%C)

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

 

17299번: 오등큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

 

풀이 과정

오큰수 문제와 비슷하게 접근하면 된다. 수열 A에 등장한 횟수를 배열에 저장하고, 오등큰수를 찾지 못한 수의 index를 스택에 저장한다. 그리고 다음 수를 인식하면서 stack top의 index에 해당하는 수보다 등장 횟수가 더 많으면 그 index의 해당하는 수의 오등큰수를 바꿔주면 된다.

 

코드

import sys

N = int(input())
A = list(map(int, input().split()))

NGF = [-1] * N
F = [0] * 1000010

stack = []

for i in A:
    F[i] += 1

for i in range(N):
    while len(stack) and F[A[i]] > F[A[stack[-1]]]:
        NGF[stack.pop()] = A[i]
    stack.append(i)

for i in NGF:
    print(i, end=' ')

 

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

 

17298번: 오큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

풀이 과정

문제를 다 읽으면 수열을 다 입력받은 상태에서 Ai의 다음 원소부터 끝까지 검색하면서 Ai보다 큰 수가 보이면 바로 출력해주는 방식이 떠오르지만 이 방법은 O(N^2) 방법이고, A의 크기가 100만이므로 시간 제한 1초 내로 해결할 수 없다.

 

스택을 이용한 더 효율적인 방법으로 풀어보자. 스택을 하나 생성하고, 오큰수가 담겨있는 배열 NGE를 만들고 -1로 초기화 하자.

 

입력 배열 A의 첫 번째 원소부터 살펴보면서 오큰수를 아직 못 찾은 수의 index를 스택에 저장하면서, 다음 index j를 확인했을 때 스택탑의 index i와 비교해 Ai < Aj이면 NGE[i] = Aj로 두고 스택에서 원소를 꺼내는 과정을 Ai < Aj가 아닐 때까지 반복해주자. 이러면 A의 원소에 대해 존재하는 모든 오큰수가 구해진다.

 

왜 이러한 방법이 성립할까? 스택에서 더 작은 수의 index일수록 위에 담겨있기 때문이다. 더 큰 수의 index는 i의 오큰수가 되어서 스택에 들어오지 않고 기존 수보다 더 작은 수의 index만 스택에 쌓여간다.

코드

import sys

N = int(input())
A = list(map(int, input().split()))
NGE = [-1 for x in range(N)]
stack = []

for j in range(N):
    if len(stack) == 0:
        stack.append(j)
        continue
    i = stack[-1]
    while A[i] < A[j]:
        NGE[i] = A[j]
        stack.pop()
        if len(stack) == 0: break
        else: i = stack[-1]
    stack.append(j)

for i in range(N): print(NGE[i], end=' ')

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

 

10799번: 쇠막대기

여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저

www.acmicpc.net

 

풀이 과정

count = 아직 안끝난 쇠막대기의 개수

answer = 정답 이라고 하자.

 

'(' 인식시 일단 쇠막대기의 시작이라고 간주 => count += 1

 

')' 인식시 앞 문자가 '('이면 앞의 '('이 쇠막대기의 시작이 아니였으므로 count -= 1, 그 후 안끝난 쇠막대기들 자르니까 answer += count를 해주고, 앞 문자가 '('이 아니면 쇠막대기의 끝이므로 count -= 1, answer += 1를 해주면 된다.

 

코드

import sys

solve = list(input())
count = 0
answer = 0
for i in solve:
    if i == '(':
        count += 1
    elif i == ')':
        if stack[-1] == '(':
            count -= 1
            answer += count
        else:
            count -= 1
            answer += 1

print(answer)

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

 

17413번: 단어 뒤집기 2

문자열 S가 주어졌을 때, 이 문자열에서 단어만 뒤집으려고 한다. 먼저, 문자열 S는 아래와과 같은 규칙을 지킨다. 알파벳 소문자('a'-'z'), 숫자('0'-'9'), 공백(' '), 특수 문자('<', '>')로만 이루어져

www.acmicpc.net

 

풀이 과정

단어를 뒤집으려면 스택에 넣었다 빼면 된다. 문자를 한글자씩 읽으면서 stack에 넣다가 tag의 시작인 '<'이나 공백 문자를 인식하면 스택에 있는 모든 문자를 스택 탑부터 출력하고, 인식한 단어를 출력하면 된다. '<'을 인식했으면 '>'을 인식하기 전까지의 단어는 스택에 넣는 과정 없이 그냥 출력해주면 된다.

 

코드

import sys

strInput = list(sys.stdin.readline().rstrip())
strInput.append(' ')
strInput2 = []
tagFlag = False
for i in strInput:
    if i == '<':
        while strInput2:
            print(strInput2.pop(), end='')
        tagFlag = True
        print('<', end='')
    elif i == '>':
        tagFlag = False
        print('>', end='')
    elif i == ' ':
        if tagFlag: print(' ', end='')
        else:
            while strInput2:
                print(strInput2.pop(), end='')
            print(' ', end='')
    else:
        if tagFlag: print(i, end='')
        else: strInput2.append(i)

 

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

 

9093번: 단어 뒤집기

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 문장이 하나 주어진다. 단어의 길이는 최대 20, 문장의 길이는 최대 1000이다. 단어와 단어 사이에는

www.acmicpc.net

 

풀이 과정

문자열1의 모든 단어를 스택에 넣었다가 문자열 2에 모두 pop하면 단어가 뒤집혀서 나올 것이다. 스택에 넣었다 빼는 방식으로 단어를 뒤집어도 되지만 파이썬 리스트에는 reverse()라는 리스트를 뒤집어주는 메소드가 존재한다. 입력을 리스트로 받은 뒤 메소드를 활용하고 join명령어로 문자열로 만들어서 출력하여 해결할 수 있다.

 

코드

import sys

T = int(sys.stdin.readline())
for i in range(T):
    beforeReverse = list(sys.stdin.readline().split())
    for j in beforeReverse:
        answer = list(j)
        answer.reverse()
        answer = ''.join(answer)
        print(answer, end=' ')
    print('')

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

 

1158번: 요세푸스 문제

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)

www.acmicpc.net

 

풀이 과정

큐를 이용하여 문제를 해결할 수 있다. 양의 정수 K가 주어지면 줄의 맨 앞에 있는 사람을 K-1번만큼 뒤로 보낸 뒤 그 뒤에 맨 앞에 있는 사람을 줄에서 빼면 된다. 이것을 큐가 빌 때 까지 반복하면 요세푸스 순열이 구해진다.

 

코드

import sys
from collections import deque

N, K = map(int, sys.stdin.readline().split())
circle = deque(range(1, N+1))
answer = []

for j in range(N):
    for i in range(K-1): circle.append(circle.popleft())
    answer.append(circle.popleft())

answer = str(answer)
answer = '<' + answer[1:-1] + '>'
print(answer)

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

 

10845번: 큐

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 

풀이 과정

스택은 파이썬에서 list로 구현할 수 있었지만 Queue는 list로 구현해서는 안된다. 0번째 원소를 insert, pop 하는 연산의 시간복잡도가 O(N)이기 때문에 절대 list로 큐를 구현해서는 안된다. collection 모듈에서 양 방향 큐인 deque를 사용해 큐를 구현해야 한다.

 

큐의 왼쪽으로 수가 들어와 오른쪽으로 나가게 구현하였고, push시 appendleft(), pop시 pop()을 사용하였다.

 

코드

import sys
from collections import deque

N = int(input())
queue = deque()

for i in range(N):
    instruction = sys.stdin.readline().split()
    if instruction[0] == 'push': queue.appendleft(instruction[1])
    elif instruction[0] == 'pop': print(queue.pop() if queue else -1)
    elif instruction[0] == 'size': print(len(queue))
    elif instruction[0] == 'empty': print(0 if queue else 1)
    elif instruction[0] == 'front': print(queue[-1] if queue else -1)
    elif instruction[0] == 'back': print(queue[0] if queue else -1)

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

 

1874번: 스택 수열

1부터 n까지에 수에 대해 차례로 [push, push, push, push, pop, pop, push, push, pop, push, push, pop, pop, pop, pop, pop] 연산을 수행하면 수열 [4, 3, 6, 8, 7, 5, 2, 1]을 얻을 수 있다.

www.acmicpc.net

 

풀이 과정

1 ~ n 까지의 수를 스택에 오름차순으로 쌓다가 필요한 수를 stack top에서 뽑아쓸 수 있다.

 

3, 2, 1은 스택 수열인가? push, push, push, pop, pop, pop을 하면 3, 2, 1이 나오니 스택 수열이다. 그렇다면 3, 1, 2는 스택 수열인가? push, push, push, pop까지는 했는데 stack top에 1이 있으니 2를 꺼낼 수 없으니 스택 수열이 아니다.

 

1. 현재의 stack top에 있는 수보다 큰 수를 꺼내야 하면 push를 계속 해서 큰 수를 쌓다가 원하는 수가 나오면 pop을 하면 된다.

2. 현재의 stack top과 같은 수를 꺼내야 하면 그냥 pop 한번 해서 수를 꺼내면 된다.

3. 현재의 stack top보다 작은 수를 꺼내야 한다면?

 

작은 수는 stack top 밑의 어딘가에 깔려있다. stack top을 꺼내지 않고서는 꺼낼 방법이 없다. 따라서 입력받은 수를 스택을 통해 만들면서, 현재의 stack top보다 작은 수를 요구하는 입력이 나온다면 스택 수열로 만들 수 없는 수열이라고 판단하면 된다.

 

코드

import sys

n = int(input())
stack = [0]
topInput = 0
noCount = False
output = []

for i in range(n):
    inPu = int(sys.stdin.readline())
    if inPu > stack[-1]:
        while inPu > stack[-1]:
            output.append('+')
            topInput += 1
            stack.append(topInput)
        output.append('-')
        del stack[-1]
    elif inPu == stack[-1]:
        output.append('-')
        del stack[-1]
    else: noCount = True

if noCount: print('NO')
else:
    for i in output:
        print(i)

+ Recent posts