(2021.06.18 - 19)
스택을 구현하는 문제였다. 내장함수를 이용하는 버전과 클래스와 함수를 만들어서 푸는 두가지 버전으로 해결해 보았다.
리스트와 내장 함수를 이용해서 스택의 효과를 내는 방법이다.
먼저 스택이라는 빈 리스트를 설정해준다.
입력값의 0번째 명령어에 따라 조건에 맞는 행동값을 준다.
알고리즘 강의에서 처럼 노드클래스와 스택클래스를 만들고 해당 함수들을 만들어 스택을 구현하는 방식이다.
리스트가 아닌 노드(노드와 포인터가 존재)로 데이터를 저장하는 방식을 사용한다.
스택 클래스는 stack = Stack() 으로 인스턴스를 실행해주고 인스턴스를 통해 각각의 메서드를 호출하는 방식으로 구현한다.
인스턴스를 실행하면 처음 생성자 메서드가 자동 호출되면서 초기 세팅값이 실행되고 이후 메서드를 통해 해당 동작을 수행한다.
from sys import stdin
class Node(): # 데이터 저장, 포인트 지정 클래스
def __init__(self, data):
self.data = data
self.next = None
class Stack(): # 데이터 입출력 방식 지정 클래스
def __init__(self): # 처음에 스택 불리면 헤드가 디폴트 none인 상태로 존재, 생성됨
self.head = None
self.len = 0
def push(self, data):
new_head = Node(data) # 제일 마지막, 최신에 들어온 값을 새로운 헤드로 저장하기 전 임시저장해둔다
new_head.next = self.head # 최신 데이터의 다음 데이터는 지금의 헤드로 지정됨
self.head = new_head # 최신 데이터가 헤드가 됨
self.len += 1 # 추가하면 길이 1증가
return
def pop(self):
if self.is_empty():
return -1
pop_data = self.head
self.head = self.head.next
self.len -= 1 # 데이터 출력돼서 빠지면 길이 -1
return pop_data.data
def top(self):
if self.is_empty():
return -1
return self.head.data
def size(self):
return self.len
def empty(self):
if self.is_empty():
return 1
return 0
def is_empty(self):
return self.head is None
n = int(input())
stack = Stack()
for _ in range(n): # 여기서 언더바는 인덱스가 딱히 의미가없어서 생략하고 범위만큼 계속하라는 뜻
cmd = stdin.readline().rstrip().split() # readlines 아니고 readline 해야 정상적으로 실행됨
order = cmd[0]
if order == 'push':
stack.push(cmd[1])
elif order == 'pop':
print(stack.pop())
elif order == 'size':
print(stack.size())
elif order == 'empty':
print(stack.empty())
elif order == 'top':
print(stack.top())
입력값이 0이면 pop, 0이 아니면 append 하는 문제
괄호가 짝을 이루고 있으면 yes, 아니면 no를 출력하는 문제
여는 괄호가 나오면 스택에 append, 닫는 괄호가 나오면 pop을 해서 조건에 맞게 결과를 출력해준다.
스택이 0일때 닫는 괄호가 나오는 경우, 입력값을 다 돌았는데도 스택이 남아 있는 경우 짝이 맞지 않다는 뜻이므로 False를 반환한다.
최소공배수를 구하는 문제이다.
사실 내장함수(최소공배수 lcm, 최대공약수 gcd) 이용하면 간단한다.
유클리드 호제법16번 참고
자연수 n, k가 주어졌을 때 이항 계수를 구하는 문제
이항 정리란 (a + b)**n, 두 항의 합에 관한 거듭제곱식을 정리한 개념이라고 볼 수 있다.
이때 변수의 계수를 이항 계수라고 하며, 일반항은 다음과 같다.
출처 링크 : 이항정리, 이항계수
해당 정리에 따라 이항 계수를 구하기 위해서는 팩토리얼을 구하는 함수를 만들어야 한다.
이후 K 가 0이면, 1을 반환하고 (0! = 1 이므로)
0이 아니면 n! / k!(n-k)! 을 구한다.
중복이 없고 순서가 있는 우측 m개 중 n개를 뽑는 조합 문제이다.
(오른쪽 다리에서 n개 만큼 뽑으면 순서대로 다리가 결정되기 때문)
이 문제도 팩토리얼을 구하는 함수를 만든 후 조합 공식으로 푼다.
24번 문제와 같이 괄호를 푸는 문제이다. 처음에는 공백까지도 처리를 해줘야한다고 생각해서 엄청 고민하고 시간을 썼지만 단순히 괄호 처리를 () 뿐만 아니라 [] 에 대해서도 해주는 방식으로 처리하면 되는 문제였다.
from sys import stdin
while True:
str_list = stdin.readline()
if str_list[0] == '.': # . 입력받으면 종료
break
stack = []
answer = True # no 조건에 걸리면 반환해줄 변수
for i in str_list: # 여는 괄호 시작되면
if i == '(' or i == '[':
stack.append(i) # 스택에 저장
elif i == ')': # 닫는 괄호 나오면
if len(stack) == 0: # 스택 비어있으면 여는 괄호 없었다는 거니까
answer = False # no 조건
break
if stack[-1] == '(': # 스택 마지막에 저장된 값이 여는 괄호면
stack.pop() # 마지막 저장된 값 빼냄
else:
answer = False # 위 조건 이외는 모두 no조건 오답처리
break
elif i == ']': # 같은 내용
if len(stack) == 0:
answer = False
break
if stack[-1] == '[':
stack.pop()
else:
answer = False
break
if answer and not stack: # answer가 True 이면서 stack 이 비었을 때. (true 가 아닌게( = false)일때 true 인 상태)
print('yes')
else:
print('no')
주어진 숫자의 배열을 만들기 위한 push(+)와 pop(-) 연산 과정을 출력하는 문제이다.
우선 값을 담을 빈 리스트 3개를 설정해 주었다.
규칙을 살펴보면 n 만큼의 정렬된 수열(숫자 열)이 입력값과 같은 순서의 수열이 되기 위해서는 총 2n 만큼을 반복해야 한다.
총 2n번을 반복하면서 입력받은 수열과 비교하면서 샘플리스트의 숫자가 작거나 같으면 stack 리스트에 append 하고, 크다면 pop을 한다.
이때 샘플리스트가 마지막까지 갔다면 (샘플리스트의 인덱스가 n과 같아졌을 때), 스택에 저장된 값을 차례로 pop 해준다.
그 전까지는 위 조건에 맞게 push(append)와 pop을 반복한다.
반복이 끝나면 새로 만들어진 리스트와 입력 받은 수열을 비교해서 같으면 + - 순서를 출력하고
다르면 NO를 출력한다.
while 문을 탈출하는 조건은 new_list가 n개 일 때다.
from sys import stdin
n = int(stdin.readline())
num_list = [int(stdin.readline().rstrip()) for _ in range(n)] # [4, 3, 6, 8, 7, 5, 2, 1]
sample = list(range(1,n + 1)) # [1, 2, 3, 4, 5, 6, 7, 8]
# 0 1 2 3 4 5 6 7
stack = []
new_list = []
result = []
while len(new_list) != n:
num_i = 0
sample_i = 0
for _ in range(2 * n):
if sample_i == n:
new_list.append(stack[-1])
stack.pop()
result.append('-')
num_i += 1
if sample_i < n:
if sample[sample_i] <= num_list[num_i]: # 8 < 8
stack.append(sample[sample_i])
sample_i += 1 # 7
result.append('+')
else:
new_list.append(stack[-1])
stack.pop()
result.append('-')
num_i += 1 # 3 >> 8
if new_list == num_list:
for sign in result:
print(sign)
else:
print('NO')
스택, 클래스, 메서드, 인스턴스, 모듈, 노드, 경우의 수