자연수 n이 매개변수로 주어질 때, 연속된 자연수들로 n을 표현하는 방법의 수를 return하는 solution를 완성해주세요.
제한사항
n은 10,000 이하의 자연수 입니다.
풀이
1 2 3 4 5 6 7 8 9 10 11 12 13
defsolution(n): q = [1] answer, i, total = 1, 1, 1 mid = int((n+1) / 2) # 절반보다 큰 값부터는 값이 없으니 절반까지 반복문 실행 while i < mid: i += 1 total += i q.append(i) while total > n: total -= q.pop(0) if total == n: answer += 1 return answer
defjosephus(n,k): res = [] q = Queue() # 직접 구현한 Queue 클래스 for i inrange(n): q.enqueue(i+1) while q.front.next: # 끝에서 2번째 원소까지 반복 for _ inrange(k-1): q.enqueue(q.dequeue()) res.append(q.dequeue()) res.append(q.dequeue()) # 마지막 원소 출력 return res
1번부터 N 번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K 번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.
N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.
예시
입력: 7, 3
출력: [3, 6, 2, 7, 5, 1, 4]
1. list로 풀기
예시대로 3번째 마다 사람을 제거하려면, 처음에는 시작점이니 2번만 인덱스를 이동하고 제거한 후 이 후에는 3번 인덱스를 이동해서 제거한다.
첫 시작을 0이 아닌 -1로 시작하는 점에 유의하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defjosephus(n,k): res = [] line = [1for _ inrange(n)] # 값이 1이면 제거 대상, 0이면 제거 완료 i = -1
for _ inrange(n-1): count = 0 while count < k: i = (i + 1) % n # i는 0~6까지 순회해야하므로 나머지로 계산한다. if line[i]: # line의 원소가 0이 아니면... count += 1 line[i] = 0 res.append(i+1)
res.append(line.index(1)+1) return res
line 배열을 1로 초기화 해준다. 1은 아직 제거안된 요소이고 0은 제거된 요소로 처리
마지막 1개가 남을 때 까지 반복하므로 n-1회 반복한다.
count 변수는 제거되지 않은 원소를 지나온 순서를 카운팅하기 위해 사용한다.
0 ~ 6까지 index가 순회해야하므로, n으로 나눈 나머지 값을 이용한다.
i를 순회하면서 line의 요소가 0이 아니면, 즉 아직 제거되지 않았으면 순서를 카운팅 해준다.
순서를 카운팅 해서 k번째 순서에 도달하면, 반복을 멈추고 해당 index 요소를 0으로 바꾼다. (요소 제거)
해당 index는 0부터 시작했으므로, 결과 배열에 넣어줄 땐 +1을 해준다. 왜냐하면 문제에선 1부터 시작한다 했으니 때문이다.
이렇게 n-1번 반복하게되면 line의 요소는 1개 남는다. 이 때는 index 메서드를 사용하여 1인 요소의 index를 구한 뒤 결과배열에 추가한다. 이 때도 + 1 을 해줘야한다.
defsolution(int_arr): for i inrange(len(int_arr)): int = int_arr[i] result = -1 for j inrange(i,len(int_arr)): ifint < int_arr[j]: result = int_arr[j] break print(f"{int} --> {result}")
스택
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defsolution*by_stack(int_arr): n = len(int_arr) s = [] res = [-1for * inrange(len(int_arr))]
for i inrange(n-1,-1,-1): while s: if s[-1] > int_arr[i]: res[i] = s[-1] break else: s.pop() s.append(int_arr[i])
for i inrange(n): print(f"{int_arr[i]} --> {res[i]}")
현재 원소와 오른쪽 원소를 비교하므로, 오른쪽에서 왼쪽으로 이동하면서 비교하면 수월하다.
문제에서 요구하는 것은 현재 원소의 오른쪽 값 중 가장 가까운 값이므로, 오른쪽 부터 왼쪽으로 가면서 원소를 저장했다면 꺼낼 때는 역순으로 꺼내서 비교한다.
stack을 빈 상태로 초기화
res 배열을 -1로 배열 길이 만큼 초기화
역순으로 순회를 하면서 stack이 비어있으면, 원소를 추가한다.
만약 stack에 값이 있다면, 스택의 값들과 현재 원소를 비교한다.
스택의 값이 크다면 해당 원소의 index에 위치하는 res 배열에 스택의 값을 할당하고 해당 원소를 stack 저장
defsolution(str): priority = {'+':2,'-':2,'*':1,'/':1} result = '' s = []
for x instr: if x.isnumeric(): result += x elif x == '(': s.append(x) elif x == ')': while s[-1] != "(": result += s.pop() s.pop() elif x in priority: if s and s[-1] != '('and priority[s[-1]] < priority[x]: result += s.pop() s.append(x)
while s: result += s.pop()
return result
코딩테스트를 본다고 생각하고 리스트를 활용하여 위 문제를 풀어보았다.
isnumeric() 함수는 문자열이 숫자인지 판단하는 메서드이다.
stack의 top을 의미하는 s[-1] 슬라이싱을 활용하였다.
빈 리스트는 논리값이 False라는 점을 활용하여 while 반복문을 실행했다.
후위 표기법 계산하기
문자열을 순회하면서 해당 문자가 숫자면 정수형으로 변환하여 스택에 push
연산자이면 스택에서 두 수를 pop하여 계산
스택은 후입선출이므로, 처음 pop한 수를 n2, 두번째 pop한 수를 n1으로 두고 (n1 연산자 n2)로 계산한다.
계산결과를 스택에 push
스택에 마지막에 저장된 값이 결과값이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defeval_postfix(expression): s = [] for exp in expression: if exp.isnumeric(): s.append(int(exp)) elif exp != " ": n2 = s.pop() n1 = s.pop() if exp == '+': res = n1 + n2 elif exp == '-': res = n1 - n2 elif exp == '*': res = n1 * n2 else: res = n1 / n2 s.append(res) return s[0]
defsolution(str): priority = {'+':2,'-':2,'*':1,'/':1} s = Stack()
result = '' for x instr: if x notin priority.keys(): result += x else: if s.top == None: s.push(x) else: if priority[s.top.data] < priority[x]: s_pop = s.pop() result += s_pop s.push(x)
whilenot s.is_empty(): s_pop = s.pop() result += s_pop
return result
아래는 if 문으 조금 줄여보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defsolution(str): priority = {'+':2,'-':2,'*':1,'/':1} s = Stack()
result = '' for x instr: if x notin priority.keys(): result += x else: ifnot s.is_empty() and priority[s.top.data] < priority[x]: s_pop = s.pop() result += s_pop s.push(x)
whilenot s.is_empty(): s_pop = s.pop() result += s_pop
for x instr: if x in brackets.values(): stack.push(x) elif x in brackets: popped = stack.pop() ifnot popped or brackets[x] != popped: returnFalse return stack.is_empty()
brackets을 관리하는 딕셔너리를 만든다.
여는 괄호면 stack에 push한다.
닫는 괄호면, 해당 닫는 괄호와 짝을 이루는 여는 괄호가 stack.pop()한 요소와 같은지 비교
만약 다르거나 pop한 요소가 None이라면 False
문제 3. 짝지어 제거하기
같은 알파벳 2개가 붙어 있는 짝을 찾습니다.
그 다음 그 둘을 제거한 뒤 앞뒤로 문자열을 이어 붙입니다.
이 과정을 반복하여 문자열이 모두 제거된다면 1을 반환하고 그렇지 않으면 0을 반환합니다.
풀이
1 2 3 4 5 6 7 8 9
defsolution(str): stack = []
for ch instr: if stack and ch == stack[-1]: stack.pop() else: stack.append(ch) return0if stack else1