시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제
45분 제한 시간 안에 세 문제를 풀고, 실제 면접에서처럼 사고 과정을 말로 설명하며, 이후 최적의 풀이를 복습합니다.
시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
이 모의 면접 사용 방법
이 수업은 실제 코딩 면접을 시뮬레이션합니다. 각 문제마다 다음을 수행해야 합니다: (1) 한 번 읽기, (2) 60초 안에 패턴 파악하기, (3) 접근법과 복잡도 말하기, (4) 풀이 작성하기, (5) 예제로 검증하기. 타이머를 설정하십시오. 쉬운 문제는 10~15분, 중간 난이도 문제는 20~25분 안에 풀어야 합니다.
풀이를 미리 보지 마십시오. 그러면 이 연습의 목적을 잃게 됩니다. 5분이 지나도 막혀 있다면 문제 설명을 다시 읽고 패턴을 드러내는 신호 단어를 찾아보십시오(정렬됨? 최솟값? 모든 조합? 부분 배열?). 스스로 막힌 상태에서 벗어나는 능력은 빠르게 푸는 능력만큼 중요합니다.
# Mock interview timer simulation
import time
class InterviewTimer:
def __init__(self, total_minutes):
self.total = total_minutes * 60
self.start = None
def begin(self, problem_name):
self.start = time.time()
print(f'TIMER STARTED: {problem_name}')
print(f'You have {self.total//60} minutes. Go!')
def checkpoint(self, label):
if self.start:
elapsed = time.time() - self.start
remaining = self.total - elapsed
print(f'[{label}] Elapsed: {elapsed:.0f}s, Remaining: {remaining:.0f}s')
# Usage in real practice:
timer = InterviewTimer(15) # 15-minute easy problem
timer.begin('Two Sum')
time.sleep(1)
timer.checkpoint('Identified pattern')쉬운 문제 1: 유효한 괄호
문제: '(', ')', '{', '}', '[', ']'만 포함하는 문자열이 주어졌을 때 입력 문자열이 유효한지 판별하십시오. 모든 여는 괄호가 올바른 순서로 동일한 유형의 괄호에 의해 닫히면 문자열은 유효합니다.
신호: 일치하는 쌍, 중요한 순서, 가장 최근에 열린 괄호를 먼저 닫아야 함 → 스택. 여는 괄호를 넣고, 닫는 괄호가 나오면 pop한 뒤 확인합니다. pop하려 할 때 스택이 비어 있거나 마지막에 남은 항목이 있으면 문자열은 유효하지 않습니다. 시간 O(n), 공간 O(n)입니다.
def is_valid(s):
stack = []
matching = {')': '(', '}': '{', ']': '['}
for char in s:
if char in '({[':
stack.append(char)
else:
if not stack or stack[-1] != matching[char]:
return False
stack.pop()
return len(stack) == 0
# Test cases
test_cases = [
('()', True),
('()[]{}' , True),
('(]', False),
('([)]', False),
('{[]}', True),
('', True), # empty string is valid
('(((', False), # unmatched opens
(')]', False), # close without open
]
for s, expected in test_cases:
result = is_valid(s)
status = 'PASS' if result == expected else 'FAIL'
print(f'{status}: is_valid({repr(s)}) = {result} (expected {expected})')쉬운 문제 2: 주식 매수 및 매도의 최적 시점
문제: prices[i]가 i일의 주가를 나타내는 배열 prices가 주어졌을 때, 한 번 매수하고 한 번 매도하여 얻을 수 있는 최대 수익을 찾으십시오(반드시 매수가 매도보다 먼저 이루어져야 합니다). 수익을 얻을 수 없다면 0을 반환하십시오.
신호: 왼쪽이 오른쪽보다 앞서야 하는 최대 차이 → 왼쪽에서 오른쪽으로 탐색하면서 지금까지의 최솟값을 추적합니다. 각 날짜에 가능한 수익은 current_price - min_so_far입니다. 최대 수익을 갱신합니다. 이 방법은 O(n)/O(1)이며 카다네 알고리즘의 특수한 경우입니다.
def max_profit(prices):
if not prices:
return 0
min_price = float('inf')
max_profit = 0
for price in prices:
if price < min_price:
min_price = price
elif price - min_price > max_profit:
max_profit = price - min_price
return max_profit
# Test cases
test_cases = [
([7, 1, 5, 3, 6, 4], 5), # buy at 1, sell at 6
([7, 6, 4, 3, 1], 0), # monotonically decreasing: no profit
([2, 4, 1], 2), # buy at 2, sell at 4
([1], 0), # single price: no transaction possible
([3, 3, 3], 0), # flat: no profit
]
for prices, expected in test_cases:
result = max_profit(prices)
status = 'PASS' if result == expected else 'FAIL'
print(f'{status}: max_profit({prices}) = {result} (expected {expected})')중간 난이도 문제 1: 세 수의 합
문제: 배열이 주어졌을 때 합이 0인 서로 다른 세 원소 조합을 모두 찾으십시오. 풀이에 중복된 세 원소 조합이 포함되어서는 안 됩니다.
패턴: 두 포인터 기법을 세 원소로 확장합니다. 배열을 sort합니다. 각 원소 nums[i]에 대해 두 포인터 left = i+1, right = n-1를 사용하여 합이 -nums[i]가 되는 쌍을 찾습니다. 동일한 값을 건너뛰도록 이동하여 중복을 제거합니다. 시간 O(n²), 출력 제외 공간 O(1)입니다. sort를 사용하면 중복 처리가 깔끔해집니다.
def three_sum(nums):
nums.sort()
result = []
n = len(nums)
for i in range(n - 2):
# Skip duplicate values for the first element
if i > 0 and nums[i] == nums[i - 1]:
continue
left, right = i + 1, n - 1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total == 0:
result.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1 # skip duplicate lefts
while left < right and nums[right] == nums[right - 1]:
right -= 1 # skip duplicate rights
left += 1; right -= 1
elif total < 0:
left += 1
else:
right -= 1
return result
print(three_sum([-1, 0, 1, 2, -1, -4])) # [[-1,-1,2],[-1,0,1]]
print(three_sum([0, 0, 0, 0])) # [[0,0,0]]
print(three_sum([])) # []
print(three_sum([1, 2, -2, -1])) # []중급 문제 2: 중복 문자가 없는 가장 긴 부분 문자열
문제: 문자열이 주어졌을 때, 중복 문자가 없는 가장 긴 부분 문자열의 길이를 구합니다.
패턴: 집합(또는 마지막 위치를 저장하는 딕셔너리)을 사용하는 슬라이딩 윈도입니다. [왼쪽, 오른쪽] 구간을 유지합니다. 각 문자를 포함하도록 오른쪽을 확장합니다. 문자가 반복되면(이미 윈도에 있으면) 중복 문자가 제거될 때까지 왼쪽에서 줄입니다. 지금까지 확인한 윈도의 최대 크기를 추적합니다. 시간 복잡도 O(n), 공간 복잡도 O(min(n, 문자 집합 크기))입니다.
def length_of_longest_substring(s):
char_index = {} # character -> last seen index
left = 0
max_len = 0
for right, char in enumerate(s):
if char in char_index and char_index[char] >= left:
left = char_index[char] + 1 # shrink window past duplicate
char_index[char] = right
max_len = max(max_len, right - left + 1)
return max_len
# Test cases
test_cases = [
('abcabcbb', 3), # 'abc'
('bbbbb', 1), # 'b'
('pwwkew', 3), # 'wke'
('', 0), # empty string
('au', 2), # full string
('dvdf', 3), # 'vdf' (skip the first d)
]
for s, expected in test_cases:
result = length_of_longest_substring(s)
status = 'PASS' if result == expected else 'FAIL'
print(f'{status}: len_longest({repr(s)}) = {result} (expected {expected})')중급 문제 3: 거스름돈
문제: 동전 단위와 목표 금액이 주어졌을 때, 해당 금액을 만드는 데 필요한 최소 동전 개수를 구합니다. 만들 수 없으면 -1을 반환합니다.
패턴: 전형적인 1차원 DP(무한 배낭 문제의 변형)입니다. dp[i]는 금액 i를 만드는 데 필요한 최소 동전 수입니다. dp[0] = 0으로 초기화하고 나머지는 모두 무한대로 설정합니다. 금액 1부터 목표 금액까지 각 금액을 순회하며 모든 동전 단위를 시도합니다. 유효한 각 동전에 대해 dp[i] = min(dp[i], dp[i - coin] + 1)을 적용합니다. 시간 복잡도 O(금액 × 동전 수), 공간 복잡도 O(금액)입니다.
def coin_change(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0 # 0 coins to make amount 0
for i in range(1, amount + 1):
for coin in coins:
if coin <= i and dp[i - coin] + 1 < dp[i]:
dp[i] = dp[i - coin] + 1
return dp[amount] if dp[amount] != float('inf') else -1
# Test cases
test_cases = [
([1, 5, 11], 15, 3), # 11+1+1+1+1... wait: 11+1+1+1+1=5 coins? No: 5+5+5=3
([2], 3, -1), # impossible (only even coins)
([1], 0, 0), # 0 coins for amount 0
([1, 2, 5], 11, 3), # 5+5+1
([186, 419, 83, 408], 6249, 20), # stress test
]
for coins, amount, expected in test_cases:
result = coin_change(coins, amount)
status = 'PASS' if result == expected else 'FAIL'
print(f'{status}: coin_change({coins}, {amount}) = {result} (expected {expected})')시간이 부족할 때의 문제 해결 작업 흐름
시간이 부족할 때는 다음 순서로 우선순위를 두십시오: (1) 미완성 최적 해법보다 올바른 출력이 나오는 작동하는 완전 탐색 해법, (2) 경계 사례를 명확히 처리하기, (3) 요령 있는 한 줄 코드보다 깔끔하고 읽기 쉬운 코드 작성. 면접관은 미묘한 버그가 있는 O(n) 해법보다 모든 테스트 사례를 통과하는 깔끔한 O(n²) 해법을 선호합니다.
O(n²) 해법이 잘못되었다는 것을 깨달았더라도 중간에 포기하지 마십시오. 끝까지 완성하고 테스트한 다음, 시간이 남으면 최적화하겠다고 제안하십시오. 절반만 작성된 최적 해법은 완전하지만 비최적인 해법보다 낮은 평가를 받습니다.
# Priority order when time runs out
priority = [
('First priority', 'Correct brute-force that passes all test cases'),
('Second priority', 'Optimal solution with bugs is WORSE than suboptimal correct'),
('Third priority', 'Edge cases handled visibly (empty input, single element, negatives)'),
('Fourth priority', 'Clean variable names and readable code'),
('Fifth priority', 'Add complexity statement as a comment at the top'),
]
print('Under time pressure, prioritise:')
for priority_level, desc in priority:
print(f' {priority_level}: {desc}')
# Adding complexity as a comment
def two_sum_commented(nums, target):
# Time: O(n), Space: O(n)
seen = {}
for i, n in enumerate(nums):
complement = target - n
if complement in seen:
return [seen[complement], i]
seen[n] = i
return []해법 검토: 다섯 가지 질문
'끝났습니다'라고 말하기 전에 다음 다섯 가지 질문을 스스로에게 해 보십시오.
- 빈 입력을 처리하나요?
[],'',None, n=0 - 요소가 하나뿐인 경우를 처리하나요? 크기가 1인 배열, 노드가 하나인 트리
- 모든 요소가 같은 경우를 처리하나요?
[5, 5, 5, 5],'aaaa' - 최솟값과 최댓값을 처리하나요? 음수, 매우 큰 정수, 0
- 시간 및 공간 복잡도를 밝혔나요? 간단한 근거를 포함한 빅오 표기법
이 다섯 가지 점검으로 면접 해법에서 발생하는 버그의 대부분을 발견할 수 있습니다. 면접관은 지원자가 스스로 테스트하기를 기대합니다. 피드백을 요청하지 않는 한 해법에 버그가 있다고 알려 주지 않을 것입니다.
# The five edge-case categories with examples
edge_cases = {
'Empty input': ['[] empty array', '"" empty string', 'None / null'],
'Single element': ['[42]', 'single node tree', 'n=1'],
'All same': ['[3,3,3,3]', '"aaaa"', 'uniform grid'],
'Extreme values': ['[-10^9, 10^9]', 'INT_MAX + 1 overflow check', '0 as input'],
'Already sorted': ['ascending + descending', 'already optimal input'],
}
for category, examples in edge_cases.items():
print(f'{category}:')
for ex in examples:
print(f' - {ex}')
print()
# Template for self-testing:
def test_my_solution(fn, test_cases):
for inputs, expected in test_cases:
result = fn(*inputs) if isinstance(inputs, tuple) else fn(inputs)
status = 'PASS' if result == expected else 'FAIL'
print(f'{status}: {inputs} => {result} (expected {expected})')후속 질문 처리하기
문제를 해결한 후 면접관은 일반적으로 후속 질문을 합니다. 흔한 유형은 다음과 같습니다.
- 'O(1) 공간으로 해결할 수 있나요?' → 제자리 수정이나 수학적 기법을 찾아보십시오
- 'n이 매우 크다면 어떻게 하나요?' → 스트리밍, 페이지 매김 또는 샘플링 접근법을 논의하십시오
- '배열이 이미 정렬되어 있다면 어떻게 하나요?' → 더 단순한 알고리즘이 존재하는 경우가 많습니다
- '이 작업을 병렬화할 수 있나요?' → 서로 독립적인 하위 문제를 식별하고 MapReduce 또는 작업 병렬성을 논의하십시오
후속 질문은 지식의 깊이와 적응력을 평가합니다. 즉시 추측하기보다 '잠시 생각해 보겠습니다'라고 말하십시오. 신중하게 멈추어 생각하는 것이 자신 있게 틀린 답을 말하는 것보다 낫습니다.
# Follow-up answers for classic problems
follow_ups = [
{
'problem': 'Find duplicate in array 1..n (space O(n) solution uses set)',
'follow_up': 'Can you do it in O(1) space without modifying input?',
'answer': 'Floyd cycle detection: treat array as linked list (slow/fast pointer)',
},
{
'problem': 'Reverse a string (space O(n) with new array)',
'follow_up': 'Can you do it in-place?',
'answer': 'Two pointers from both ends, swap until they meet: O(n) time O(1) space',
},
{
'problem': 'Find max in array: O(n) single pass',
'follow_up': 'What if the array is streamed one element at a time?',
'answer': 'Same algorithm works! Running maximum handles infinite streams',
},
{
'problem': 'Merge sorted arrays O(n+m)',
'follow_up': 'What if you have K sorted arrays?',
'answer': 'Use a min-heap of (value, array_idx, element_idx): O(n log k)',
},
]
for fu in follow_ups:
print(f'Problem: {fu["problem"]}')
print(f'Follow-up: {fu["follow_up"]}')
print(f'Answer: {fu["answer"]}\n')연습 문제: 애너그램 그룹화
문제: 문자열 배열이 주어졌을 때, 애너그램끼리 묶습니다. 그룹 목록을 반환합니다.
패턴: 빈도 맵을 키로 사용합니다. 각 문자열에 대해 문자를 sort하거나 문자 빈도 튜플을 계산하여 표준 키를 만듭니다. 리스트를 값으로 갖는 해시 맵을 사용해 이 키에 따라 문자열을 그룹화합니다. 여기서 m은 가장 긴 문자열의 길이입니다. 시간 복잡도 O(n × m log m), 공간 복잡도 O(n × m)입니다. 중첩 반복문은 필요하지 않으며 배열을 한 번만 순회하면 됩니다.
from collections import defaultdict
def group_anagrams(strs):
# Method 1: sort each string as key
groups = defaultdict(list)
for s in strs:
key = ''.join(sorted(s)) # canonical form
groups[key].append(s)
return list(groups.values())
def group_anagrams_v2(strs):
# Method 2: character count tuple as key (avoids sorting)
groups = defaultdict(list)
for s in strs:
count = [0] * 26
for c in s:
count[ord(c) - ord('a')] += 1
key = tuple(count) # immutable, hashable
groups[key].append(s)
return list(groups.values())
test = ['eat', 'tea', 'tan', 'ate', 'nat', 'bat']
result = [sorted(g) for g in group_anagrams(test)]
result.sort()
print('Groups:', result)
# [['ate','eat','tea'], ['bat'], ['nat','tan']]
print('V2:', [sorted(g) for g in sorted(group_anagrams_v2(test), key=len)])모의 면접 후 자기 평가
각 모의 면접 후 다음 기준으로 자신을 평가하십시오.
- 패턴 인식 속도: <60초 안에 패턴을 파악했나요?
- 코드 정확성: 첫 해법이 모든 테스트 사례를 통과했나요?
- 경계 사례 처리: 빈 입력, 단일 요소, 극단적인 입력을 테스트했나요?
- 의사소통: 전 과정에서 추론을 설명했나요?
- 복잡도 인식: 시간 및 공간 복잡도를 밝혔나요?
- 대처 능력: 막혔을 때 자연스럽게 방향을 전환했나요, 아니면 멈춰 버렸나요?
각 기준을 1~5점으로 평가하십시오. 다음 일주일의 연습은 가장 낮은 점수를 받은 기준에 집중하십시오. 대부분의 지원자는 패턴 인식이나 의사소통 중 하나를 개선해야 하며, 둘 다인 경우는 드뭅니다.
# Self-assessment scoring template
def self_assess(pattern_speed, code_correctness, edge_cases,
communication, complexity, recovery):
scores = {
'Pattern recognition (< 60s)': pattern_speed,
'Code correctness (all tests pass)': code_correctness,
'Edge case handling': edge_cases,
'Communication (thinking aloud)': communication,
'Complexity stated correctly': complexity,
'Recovery when stuck': recovery,
}
total = sum(scores.values())
max_total = len(scores) * 5
print('Self-Assessment Results:')
print('-'*50)
for dim, score in scores.items():
bar = '#' * score + '-' * (5 - score)
print(f'{dim:45s} [{bar}] {score}/5')
print(f'\nTotal: {total}/{max_total} ({total/max_total*100:.0f}%)')
weak = min(scores, key=scores.get)
print(f'Focus area: {weak}')
self_assess(4, 3, 4, 3, 5, 2) # example scores빠른 확인
이번 수업의 자료 구조 및 알고리즘 — 코딩 면접 준비 개념에 대한 이해도를 테스트해 보십시오.
수업 복습
이번 수업에서는 정해진 작업 흐름으로 문제에 접근하는 법 — 읽고, 60초 안에 패턴을 파악하고, 복잡도를 말하고, 코딩한 다음 다섯 가지 경계 사례 범주로 테스트하기, 시간이 부족할 때는 작동하는 완전 탐색 해법이 미완성 최적 해법보다 낫다는 것, 그리고 각 모의 연습 세션 후 여섯 가지 기준(속도, 정확성, 경계 사례, 의사소통, 복잡도, 대처 능력)에 따라 자기 평가를 하면 올바른 영역의 개선에 집중할 수 있다는 것을 배웠습니다. 다음에는 경계 사례 처리와 면접 대상자의 의사소통 모범 사례를 자세히 다룹니다.
자주 묻는 질문
“시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제” 강의는 무료인가요?
네 — “시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제”에서 뭘 배우나요?
45분 제한 시간 안에 세 문제를 풀고, 실제 면접에서처럼 사고 과정을 말로 설명하며, 이후 최적의 풀이를 복습합니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 패턴 인식 요약표
- 시간 제한 모의 면접: 쉬운 문제와 중간 난이도 문제
- 예외 상황 처리와 면접 대상자의 의사소통
- 어려운 문제 풀이: 단어 사다리 II와 외계인 사전