1. 첫 번째 코드 (정답 코드)

#괄호 균형 판단 프로그램
#(), []

while(True):
    tf=0
    line = input()
    small=0#괄호가 열리면 +1, 닫히면 -1
    large=0
    #<괄호의 균형을 맞춰야하는 문제 해결 방법>
        #문이 열릴 때마다,색을 칠해준다.
        #닫을 때 칠해진 색과 닫을 색이 일치하지 않으면 break
        #일치하면 그 색을 뽑아버린다.
    color=[]
    if len(line)==1 and line[-1]=='.':#.이 들어오면 정지
        break

    else:
        for i in line:
            if i == '(':
                small+=1
                color.append('small')
            elif i==')':
                small-=1
                if small <0: #한 번이라도 이런 경우가 생기면 에러처리를 위해 tf=-1로 변경.
                    tf=-1
                    break
                if color[-1] !='small':
                    tf=-1
                    break
                else:
                    color.pop()
            elif i=='[':
                large+=1
                color.append('large')
            elif i==']':
                large-=1
                if large <0:
                    tf=-1
                    break
                if color[-1] !='large':
                    tf=-1
                    break
                else:
                    color.pop()

    if small == 0 and large == 0 and tf==0:
        print('yes')
    else:
        print('no')

#마지막에 .을 넣어도 끝나지 않음
    #=> while문 안의 for문이 아니라, for문 시작 전에 if break문을 넣어줬음.

 

2. 정리한 코드(정답 코드)

위의 코드가 조금 지저분한 것 같아서 정리 필요.

while(True):
    tf=0 #오답이 확정일 때 -1로 구분지어주는 역할.
    
    line = input() #입력 받기

    #<괄호의 균형을 맞춰야하는 문제 해결 방법>
        #가장 최근에 열린 괄호가, 자신의 짝과 일치하는지 확인한다.
            #일치하지 않으면 break
            #일치하면 그 색을 뽑아버린다.
    stack=[]
    
    if len(line)==1 and line[-1]=='.':#.이 들어오면 정지
        break

    else:
        for i in line:
            if i == '(' or i=='[':
                stack.append(i)
            elif i==')':
                if len(stack)==0 or stack[-1] !='(':
                    tf=-1
                    break
                else:
                    stack.pop()
            elif i==']':
                if len(stack)==0 or stack[-1] !='[':
                    tf=-1
                    break
                else:
                    stack.pop()

    if len(stack)==0 and tf!=-1:
        print('yes')
    else:
        print('no')

 

3. 최종 코드 : import sys 입력만 더 효율적으로

import sys
input=sys.stdin.readline
#readline은 공백도 받으므로, rstrip()로 공백 제거.
while(True):
    tf=0 #오답이 확정일 때 -1로 구분지어주는 역할.
    
    line = input().rstrip() #입력 받기

    #<괄호의 균형을 맞춰야하는 문제 해결 방법>
        #가장 최근에 열린 괄호가, 자신의 짝과 일치하는지 확인한다.
            #일치하지 않으면 break
            #일치하면 그 색을 뽑아버린다.
    stack=[]
    
    if len(line)==1 and line[-1]=='.':#.이 들어오면 정지
        break

    else:
        for i in line:
            if i == '(' or i=='[':
                stack.append(i)
            elif i==')':
                if len(stack)==0 or stack[-1] !='(':
                    tf=-1
                    break
                else:
                    stack.pop()
            elif i==']':
                if len(stack)==0 or stack[-1] !='[':
                    tf=-1
                    break
                else:
                    stack.pop()

    if len(stack)==0 and tf!=-1:
        print('yes')
    else:
        print('no')

이때 readline은 공백도 받으므로, rstrip()로 공백을 제거해줘야한다.

1. 시간 초과 코드

첫 번째로 풀었을 때 시간 초과  코드. 시간 초과 될 것은 알았지만, 일단 써보자라고 생각하고 작성했다. 역시나 시간 초과.

import sys
input=sys.stdin.readline

m, n = map(int, input().split())

for i in range(m, n+1):
    cnt=False #합성수 수
    for j in range(2, 1000001):
        if i % j ==0 and i !=j:
            cnt=True
    if cnt == False:
        print(i)

에라토스테네스의 체를 활용하여 경우의 수를 확 줄여서 문제를 푸는 것이었다.

결국 1~100 사이의 소수를 찾는다면, 루트 100 = 10 까지만 나눠서 확인해보면(2~10의 배수가 아닌 것이 확인되면)

소수라는 것을 확신할 수 있다는 뜻이다. 2의 배수, 3의 배수, 4의 배수 ... 차례로 모두 제거한다고 생각해보면, 10의 배수까지만 제거할 수 있다. 11*1~11*10까지는 이미 1~10의 배수에서 걸러졌고, 다음 11*11 부터는 해당 범위를 초과해서 볼 필요도 없다.

[에라토스테네스의 체 내용 참고]

https://namu.wiki/w/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98%20%EC%B2%B4

 

코드는 다음과 같다.

import sys
input=sys.stdin.readline
m, n = map(int, input().split())

for i in range(m, n+1):
	if i == 1: #1제거
    	continue
    for j in range(2, int(i**0.5) + 1): # 해당 수의 제곱근까지만 확인해주면 됨.
    	if i % j == 0: #나누어지면 멈추고,
        	break
    else:
    	print(i) #나누어지지 않으면 출력한다.

 

오랜 시간의 고민 끝에, k층의 n호는, k-1층의 1호부터 n호까지의 합만큼의 인원이 산다는 것을 파악하였다.

그래서 재귀함수로 아래와 같은 코드를 짰는데, 시간 초과가 떴다.

 

1.재귀함수 이용

1) 1층과 2층 요소 출력을 위한 sigma 구현 공부

처음에 이 함수를 짜기 위해서, python 내에서 sigma를 정의하는 방법을 공부했다.

###sigma k : 1층의 n호 요소 출력하기

def sigma(n):
	result=0
    for k in range(1, n+1): #1부터 n까지
    	result +=k #1부터 n까지를 계속 더한다. 1+2+3+...+n
    return result

print(sigma(3)) #1층의 3호 요소 출력하기 : 1+2+3

###sigma k(k+1)/2 : 2층의 n호 요소 출력하기

def sigma2(n):
	result=0
    for i in range(1, n+1): #1부터 n까지
    	result += sigma(i)
    return result

print(sigma2(3)) #2층의 3호 요소 출력하기 : sigma(1)+ sigma(2) + sigma(3)

이렇게 계속 정의해 나가면 되겠지만, 입력 범위가 넓기 때문에 이렇게 계속 만드는 것은 불가능하다.

따라서 재귀함수로 만들어보고자 하여 아래와 같은 코드를 완성했다.

 

2) 재귀 함수 코드

import sys

input=sys.stdin.readline

T=int(input())
for _ in range(T):
    k=int(input()) #k층. 단계. sigma 횟수. 0층이 요소. 1층=1번 시그마, 2층=2번 시그마
    n=int(input()) #n호. 해당 시그마에서 n번까지 더해야함.
    
    def sigma_depth(k, n):
        if k==1: #초항 정의
            result=0
            for i in range(1, n+1): #i부터 n까지
                result +=i #다 더한다.1+2+...+n
            # print(k,'일 때 result=',result)
            return result
        else:
            result=0
            for i in range(1, n+1): #1부터 n까지
                result += sigma_depth(k-1, i) #아래층의 i까지의 합을 다 더한 것.
                # print(k,'일 때',i,'번째')
            # print(k,'일 때 result=',result)
            return result
            
	print(sigma_depth(k, n))

위 코드는 아래와 같은 원리로 정답이다.

그런데, 예시 1번에서는 계산이 얼마 되지 않아서 괜찮지만, 예시 2번부터는 굉장히 많은 계산이 이루어진다. 심지어 이미 계산했던 것들도 반복해서 계산해야하는 비효율적인 계산이 이루어진다.

=> 이를 행렬에 저장해놓고 인덱스로 가져다가 쓰는 방법으로 해결할 수 있을까 싶다. 인덱스의 시간 복잡도가 O(1)인 것을 확인하였다.

하지만 생각보다 복잡하다.

 

2. 간단한 점화식을 활용하여 계산하기

그래서 차분하게 써놓고 생각해보니

 matrix[k][n]=matrix[k-1][n]+matrix[k][n-1]과 같다.

그런데 결국 마지막 값만 출력하면 되기 때문에, 모든 층의 값들을 저장해둘 필요가 없다.

쉽게 생각하면 [바로 앞 호수 + 아래 층의 같은 호수]이기 때문에, 한 층을 한 호수씩 업데이트 해나간다고 생각하면 아래와 같이 코드를 간결하게 짤 수 있다.

 

import sys
input=sys.stdin.readline

t=int(input())

for _ in range(t):
	floor = int(input()) #층수
    num = int(input()) #호수
    f0 = [x for x in range(1, num+1): #0층 리스트. 1~n호까지
    for k in range(floor): #층 수 만큼 반복
    	for i in range(1, num): #1~n-1까지
        	f0[i] +=f0[i-1]
    print(f0[-1])

정답만 출력해내면 된다는 것을 기억하자.

 

 

 

 

+ Recent posts