C++ 코딩 테스트 준비: 백준·프로그래머스 유형별 STL 활용과 입출력 최적화

이 글의 핵심

C++로 코딩 테스트를 볼 때는 알고리즘보다 STL을 제대로 못 써서 시간 초과나 오답이 나는 경우가 많습니다. map과 unordered_map, vector와 set 중 무엇을 고를지, sort와 lower_bound 같은 algorithm 함수를 어떻게 조합할지를 문제 유형과 연결해 설명하고, 엣지 케이스 체크와 두 플랫폼의 입출력 방식 차이도 짚습니다.

들어가며: C++ 코딩 테스트 면접, 무엇을 준비해야 할까?

코딩 테스트(알고리즘·자료구조 문제를 제한 시간 안에 코드로 푸는 시험) 면접은 대부분 화이트보드 또는 온라인 IDE에서 30~60분 안에 알고리즘 문제를 푸는 형태입니다. 회사마다 난이도는 다르지만, 자료구조·알고리즘 기본기와 C++ STL 활용 능력을 평가합니다. 이 글은 자주 나오는 문제 유형, STL 필수 함수, 실전 팁을 정리한 면접 준비 가이드입니다.

이 글에서 다루는 것:

  • 코딩 테스트 면접에서 자주 나오는 알고리즘 유형 7가지
  • C++ STL 필수 함수 정리 (vector, map, set, algorithm)
  • 시간복잡도 분석과 최적화 전략
  • 실전 팁: 입출력 최적화, 엣지 경우, 코드 가독성
  • 면접 당일 체크리스트

코딩 테스트에서 자주 나오는 알고리즘 유형과 준비 흐름을 요약하면 아래와 같습니다.

flowchart LR
  subgraph type[유형]
    S[정렬·탐색]
    D[DP]
    G[그래프]
    T[트리]
  end
  subgraph prep[준비]
    STL[STL 활용]
    IO[입출력 최적화]
    TC[시간복잡도]
  end
  type --> prep

자주 나오는 알고리즘 유형 7가지

정렬과 탐색

대표 문제:

  • 배열 정렬 후 특정 값 찾기 (이진 탐색)
  • K번째 큰/작은 원소 찾기
  • 두 배열의 교집합·합집합

핵심 STL:

  • std::sort(v.begin(), v.end())
  • std::binary_search, std::lower_bound, std::upper_bound
  • std::nth_element (K번째 원소)

언제 정렬을 쓰나요?
정렬은 O(N log N)이라 비싼 연산이지만, 정렬 후에는 이진 탐색(O(log N)), 투 포인터(O(N)) 같은 효율적인 알고리즘을 쓸 수 있습니다. 무식하게 O(N²)로 풀 문제를 정렬 + 이진 탐색으로 O(N log N)에 해결할 수 있습니다.

lower_bound vs upper_bound:

  • lower_bound(x): x 이상인 첫 위치
  • upper_bound(x): x 초과인 첫 위치
  • 차이: upper_bound - lower_bound = x의 개수

예시 코드 (복사해 붙여넣은 뒤 g++ -std=c++17 -o binsearch_demo binsearch_demo.cpp && ./binsearch_demo 로 실행 가능):

// 복사해 붙여넣은 뒤: g++ -std=c++17 -o binsearch_demo binsearch_demo.cpp && ./binsearch_demo
#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> v = {3, 1, 4, 1, 5};
    std::sort(v.begin(), v.end());  // {1, 1, 3, 4, 5}
    bool found = std::binary_search(v.begin(), v.end(), 3);
    auto it = std::lower_bound(v.begin(), v.end(), 3);
    std::cout << found << " " << (it - v.begin()) << "\n";  // 1 2
    return 0;
}

실행 결과: 1 2 (found와 인덱스)가 한 줄 출력됩니다.

해시맵 (빈도수, 중복 체크)

대표 문제:

  • 배열에서 중복 원소 찾기
  • 두 문자열이 애너그램인지 확인
  • 부분합이 K인 구간 개수 (누적합 + 해시맵)

핵심 STL:

  • std::unordered_map<int, int> (O(1) 평균 접근)
  • std::unordered_set<int> (중복 체크)

해시맵의 핵심:
해시맵은 O(1) 평균 시간에 삽입·삭제·탐색이 가능합니다. 이중 반복문으로 O(N²)에 풀어야 할 문제를 O(N)에 해결할 수 있는 경우가 많습니다.

Two Sum 문제 예시:
“배열에서 합이 K인 두 원소 찾기”

무식한 방법 (O(N²)):

for (int i = 0; i < n; ++i) {
    for (int j = i+1; j < n; ++j) {
        if (arr[i] + arr[j] == K) { /* 찾음 */ }
    }
}

해시맵 방법 (O(N)):

std::unordered_set<int> seen;
for (int x : arr) {
    if (seen.count(K - x)) { /* 찾음 */ }
    seen.insert(x);
}

예시 코드:

std::unordered_map<int, int> freq;
for (int x : arr) {
    freq[x]++;
}

// 가장 빈도 높은 원소
int maxFreq = 0, result = 0;
for (auto& [num, cnt] : freq) {
    if (cnt > maxFreq) {
        maxFreq = cnt;
        result = num;
    }
}

투 포인터 (Two Pointers)

대표 문제:

  • 정렬된 배열에서 합이 K인 두 원소 찾기
  • 부분 배열의 합이 K 이하인 최대 길이
  • 회문(Palindrome) 판별

핵심 아이디어:

  • 왼쪽(left)과 오른쪽(right) 포인터를 동시에 이동하며 O(N)에 해결

예시 코드:

// 정렬된 배열에서 합이 target인 두 원소
std::vector<int> v = {1, 2, 3, 4, 5};
int target = 7;
int left = 0, right = v.size() - 1;

while (left < right) {
    int sum = v[left] + v[right];
    if (sum == target) {
        std::cout << v[left] << ", " << v[right] << '\n';
        break;
    } else if (sum < target) {
        left++;
    } else {
        right--;
    }
}

동적 계획법 (Dynamic Programming, DP)

DP(동적 계획법—작은 부분 문제의 답을 저장해 두고 큰 문제를 풀 때 재사용하는 알고리즘 기법)의 대표 문제는 다음과 같습니다.

대표 문제:

  • 피보나치 수열
  • 최장 증가 부분 수열 (LIS)
  • 배낭 문제 (Knapsack)
  • 최단 경로 (DP + 그래프)

핵심 아이디어:

  • 메모이제이션: 이미 계산한 값을 배열에 저장해서 재사용

DP를 쓰는 이유:
재귀로 풀면 중복 계산이 많습니다. 예를 들어 fib(5)를 계산할 때:

  • fib(5) = fib(4) + fib(3)
  • fib(4) = fib(3) + fib(2)
  • fib(3)이 두 번 계산됩니다.

fib(50)을 순수 재귀로 계산하면 수십억 번 함수 호출이 일어나지만, DP를 쓰면 50번만 계산합니다.

Top-Down vs Bottom-Up:

  • Top-Down (메모이제이션): 재귀 + 캐시. 필요한 값만 계산.
  • Bottom-Up (타뷸레이션): 반복문으로 작은 문제부터 순서대로 계산. 보통 더 빠름.

예시 코드 (피보나치):

std::vector<long long> dp(100, -1);

long long fib(int n) {
    if (n <= 1) return n;
    if (dp[n] != -1) return dp[n];  // 이미 계산됨
    return dp[n] = fib(n-1) + fib(n-2);
}

Bottom-Up 방식 (더 빠름):

std::vector<long long> dp(100);
dp[0] = 0; dp[1] = 1;
for (int i = 2; i < 100; ++i) {
    dp[i] = dp[i-1] + dp[i-2];
}

그래프 탐색 (BFS, DFS)

그래프(정점과 간선으로 이루어진 자료구조. 예: 지도에서 도시=정점, 도로=간선) 탐색의 대표 문제는 다음과 같습니다.

대표 문제:

  • 미로 최단 경로 (BFS)
  • 연결된 컴포넌트 개수 (DFS/BFS)
  • 사이클 탐지
  • 위상 정렬

핵심 STL:

  • std::queue<int> (BFS)
  • std::stack<int> 또는 재귀 (DFS)
  • std::vector<std::vector<int>> (인접 리스트)

BFS 예시:

std::vector<std::vector<int>> graph(n);
std::vector<bool> visited(n, false);
std::queue<int> q;

q.push(start);
visited[start] = true;

while (!q.empty()) {
    int node = q.front();
    q.pop();
    
    for (int neighbor : graph[node]) {
        if (!visited[neighbor]) {
            visited[neighbor] = true;
            q.push(neighbor);
        }
    }
}

그리디 (Greedy)

대표 문제:

  • 회의실 배정 (활동 선택 문제)
  • 동전 거스름돈 (특정 조건)
  • 최소 신장 트리 (Kruskal, Prim)

핵심 아이디어:

  • 매 순간 최선의 선택을 하면 전체 최적해가 나오는 경우

예시 코드 (회의실 배정):

struct Meeting {
    int start, end;
};

std::vector<Meeting> meetings = {{1, 3}, {2, 4}, {3, 5}};

// 끝나는 시간 기준 정렬
std::sort(meetings.begin(), meetings.end(), [](const Meeting& a, const Meeting& b) {
    return a.end < b.end;
});

int count = 0, lastEnd = 0;
for (auto& m : meetings) {
    if (m.start >= lastEnd) {
        count++;
        lastEnd = m.end;
    }
}

백트래킹 (Backtracking)

대표 문제:

  • N-Queen
  • 순열·조합 생성
  • 스도쿠 풀이

핵심 아이디어:

  • 재귀적으로 모든 경우를 시도하되, 조건에 맞지 않으면 즉시 되돌아옴

예시 코드 (순열):

void permute(std::vector<int>& nums, int start) {
    if (start == nums.size()) {
        // 순열 하나 완성
        for (int x : nums) std::cout << x << ' ';
        std::cout << '\n';
        return;
    }
    
    for (int i = start; i < nums.size(); ++i) {
        std::swap(nums[start], nums[i]);
        permute(nums, start + 1);
        std::swap(nums[start], nums[i]);  // 백트래킹
    }
}

또는 STL:

std::vector<int> v = {1, 2, 3};
std::sort(v.begin(), v.end());
do {
    for (int x : v) std::cout << x << ' ';
    std::cout << '\n';
} while (std::next_permutation(v.begin(), v.end()));

C++ STL 필수 함수 정리

vector

std::vector<int> v = {1, 2, 3};
v.push_back(4);           // 끝에 추가
v.pop_back();             // 끝에서 제거
v.size();                 // 크기
v.empty();                // 비어 있는지
v.clear();                // 전체 삭제
v[0];                     // 인덱스 접근 (범위 체크 X)
v.at(0);                  // 범위 체크 O (예외 발생)

map (정렬된 키)

std::map<std::string, int> m;
m["apple"] = 1;
m["banana"] = 2;

if (m.count("apple")) {   // 키 존재 여부
    std::cout << m["apple"] << '\n';
}

for (auto& [key, val] : m) {  // 키 순서대로 순회
    std::cout << key << ": " << val << '\n';
}

unordered_map (해시맵, O(1) 평균)

std::unordered_map<int, int> freq;
for (int x : arr) {
    freq[x]++;
}

set (중복 없는 정렬된 집합)

std::set<int> s = {3, 1, 4, 1, 5};  // {1, 3, 4, 5}
s.insert(2);
s.erase(3);
bool exists = s.count(4);  // 1 (있음) 또는 0 (없음)

algorithm 헤더

#include <algorithm>

std::sort(v.begin(), v.end());                    // 오름차순 정렬
std::sort(v.begin(), v.end(), std::greater<>());  // 내림차순

std::reverse(v.begin(), v.end());                 // 뒤집기

auto it = std::find(v.begin(), v.end(), 42);      // 값 찾기
if (it != v.end()) { /* 찾음 */ }

int maxVal = *std::max_element(v.begin(), v.end());
int minVal = *std::min_element(v.begin(), v.end());

std::next_permutation(v.begin(), v.end());        // 다음 순열

시간복잡도 분석과 최적화

자주 나오는 시간복잡도

복잡도N=100N=10,000N=1,000,000예시 알고리즘
O(1)111해시맵 접근
O(log N)71320이진 탐색
O(N)10010,0001,000,000선형 탐색, 순회
O(N log N)700130,00020,000,000정렬 (merge sort)
O(N²)10,000100,000,0001,000,000,000,000이중 반복문
O(2^N)1.3×10³⁰--완전 탐색 (백트래킹)

제한 시간과 복잡도

1초 제한에서 대략:

  • O(N): N ≤ 10⁸
  • O(N log N): N ≤ 10⁶
  • O(N²): N ≤ 10⁴
  • O(N³): N ≤ 500

왜 이런 기준인가요?
현대 컴퓨터는 1초에 약 10⁸~10⁹ 번의 기본 연산을 수행할 수 있습니다. 하지만 실제 알고리즘은 기본 연산 외에 함수 호출, 메모리 접근, 분기 등의 오버헤드가 있으므로, 안전하게 10⁸ 정도로 잡습니다.

구체적인 예시:

  • N=10⁶, O(N²) → 10¹² 연산 → 1000초 (시간 초과)
  • N=10⁶, O(N log N) → 2×10⁷ 연산 → 0.2초 (통과)

면접에서 자주 하는 실수: O(N²) 알고리즘을 N=10⁶ 입력에 적용 → 시간 초과

팁: 문제에서 N의 범위를 보고 허용되는 복잡도를 역산하세요.

  • N ≤ 10 → O(N!) 가능 (완전 탐색)
  • N ≤ 20 → O(2^N) 가능 (비트마스크 DP)
  • N ≤ 500 → O(N³) 가능 (플로이드-워셜)
  • N ≤ 10⁴ → O(N²) 가능 (이중 반복문)
  • N ≤ 10⁶ → O(N log N) 필요 (정렬, 세그먼트 트리)
  • N ≤ 10⁸ → O(N) 필요 (선형 알고리즘)

최적화 전략

1. 불필요한 반복 제거:

// ❌ 매번 size() 호출
for (int i = 0; i < v.size(); ++i) { }

// ✅ 한 번만 계산
int n = v.size();
for (int i = 0; i < n; ++i) { }

2. 해시맵으로 O(N²) → O(N):

// ❌ O(N²)
for (int i = 0; i < n; ++i) {
    for (int j = i+1; j < n; ++j) {
        if (arr[i] + arr[j] == target) { /* ... */ }
    }
}

// ✅ O(N)
std::unordered_set<int> seen;
for (int x : arr) {
    if (seen.count(target - x)) {
        // 찾음
    }
    seen.insert(x);
}

3. 정렬 활용:

정렬하면 O(N log N)이지만, 이후 이진 탐색·투 포인터로 O(N²) → O(N log N) 또는 O(N) 가능.


3-1. 컨테이너 선택과 자주 쓰는 함수

컨테이너 선택 가이드

요구사항추천 컨테이너시간복잡도
순서 유지, 빠른 접근vector접근 O(1), 삽입/삭제 O(N)
중복 없는 집합, 정렬set삽입/삭제/탐색 O(log N)
중복 없는 집합, 순서 무관unordered_set평균 O(1)
키-값 쌍, 정렬mapO(log N)
키-값 쌍, 순서 무관unordered_map평균 O(1)
큐 (FIFO)queueO(1)
스택 (LIFO)stackO(1)
우선순위 큐priority_queue삽입/삭제 O(log N)

algorithm 헤더 자주 쓰는 함수

#include <algorithm>

// 정렬
std::sort(v.begin(), v.end());
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });  // 내림차순

// 탐색
auto it = std::find(v.begin(), v.end(), 42);
bool found = std::binary_search(v.begin(), v.end(), 42);  // 정렬 필요

// 최소/최대
int maxVal = *std::max_element(v.begin(), v.end());
int minVal = *std::min_element(v.begin(), v.end());

// 중복 제거 (정렬 후)
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());

// 순열
std::next_permutation(v.begin(), v.end());

// 부분 정렬 (K번째 원소)
std::nth_element(v.begin(), v.begin() + k, v.end());

string 함수

std::string s = "hello";
s.size();                     // 길이
s.substr(1, 3);               // "ell" (시작 인덱스, 길이)
s.find("ll");                 // 2 (위치), 없으면 std::string::npos
s.rfind("l");                 // 3 (뒤에서부터 찾기)

// 문자열 → 숫자
int num = std::stoi("123");
long long big = std::stoll("123456789012");

// 숫자 → 문자열
std::string str = std::to_string(123);

실전 팁: 입출력, 엣지 경우, 가독성

입출력 최적화

백준·프로그래머스 같은 온라인 저지에서는 입출력이 많으면 시간 초과가 날 수 있습니다.

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);  // ✅ C 스트림과 동기화 끄기
    cin.tie(NULL);                     // ✅ cin/cout 버퍼 분리
    
    int n;
    cin >> n;
    
    // 출력은 endl 대신 '\n'
    cout << n << '\n';  // ✅ 빠름
    // cout << n << endl;  // ❌ 매번 flush로 느림
    
    return 0;
}

왜 이렇게 해야 하나요?

sync_with_stdio(false):
기본적으로 C++ 스트림(cin, cout)과 C 스트림(scanf, printf)은 동기화되어 있습니다. 섞어 써도 출력 순서가 보장됩니다. 하지만 이 동기화는 오버헤드가 큽니다. C 스트림을 안 쓴다면, 동기화를 끄면 2~3배 빨라집니다.

cin.tie(NULL):
기본적으로 cin은 cout에 묶여(tie) 있습니다. cin으로 입력받기 전에 cout 버퍼를 자동으로 flush합니다. 이는 대화형 프로그램에서는 유용하지만, 코딩 테스트에서는 불필요한 flush로 느려집니다.

endl vs \n:
endl은 줄바꿈 + 버퍼 flush입니다. 출력이 10만 번이면 10만 번 flush가 일어나 극도로 느립니다. '\n'은 줄바꿈만 하며, 버퍼는 자동으로 또는 프로그램 종료 시 flush됩니다.

실전 효과:
입력 10만 줄, 출력 10만 줄인 문제에서:

  • 최적화 없음: 3~5초 (시간 초과)
  • 최적화 적용: 0.3~0.5초 (통과)

관련 글: C++ 코딩테스트 입출력 치트시트

엣지 케이스 체크

면접관이 자주 확인하는 것:

  • 빈 입력 (N=0, 빈 배열)
  • 최소/최대값 (N=1, N=10⁶)
  • 중복 원소 (모든 원소가 같음)
  • 음수·0 (문제에서 양수만 가정하지 않았는지)
  • 오버플로우 (int 범위 초과 → long long 사용)

예시:

// ❌ N=0일 때 크래시
int maxVal = v[0];
for (int x : v) maxVal = std::max(maxVal, x);

// ✅ 빈 배열 처리
if (v.empty()) return -1;  // 또는 예외 처리
int maxVal = *std::max_element(v.begin(), v.end());

코드 가독성

면접에서는 정답만큼 “읽기 쉬운 코드”도 중요합니다.

1. 의미 있는 변수명:

// ❌
int a = 0, b = 0;

// ✅
int leftPointer = 0, rightPointer = n - 1;

2. 함수 분리:

// ✅ 복잡한 로직은 함수로 분리
bool isPrime(int n) {
    if (n < 2) return false;
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) return false;
    }
    return true;
}

3. 주석 (필요 시):

// 투 포인터로 합이 target인 쌍 찾기
int left = 0, right = n - 1;

백준과 프로그래머스의 차이

같은 알고리즘이라도 두 플랫폼은 코드를 제출하는 형태가 다릅니다.

// 백준: main에서 표준 입력을 직접 읽고 표준 출력으로 답을 쓴다
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n;
    std::cin >> n;
    std::cout << n * 2 << '\n';
}

// 프로그래머스: 정해진 시그니처의 solution 함수만 구현한다 (입출력은 채점기가 처리)
int solution(int n) {
    return n * 2;
}

백준에 익숙한 사람이 프로그래머스에서 가장 자주 하는 실수는 solution 안에서 cin으로 입력을 읽으려는 것이고, 반대로 프로그래머스에 익숙하면 백준에서 입출력 최적화 두 줄을 잊어 시간 초과가 납니다(입출력 최적화 수치는 C++ I/O 병목 줄이기에서 직접 측정했습니다). 또 solution에서 전역 변수를 쓰면 이전 호출의 값이 남아 있을 수 있으므로, 전역 상태는 함수 시작에서 반드시 초기화하는 습관을 들이는 것이 안전합니다.

메모리 초과와 스택 오버플로우

int main() {
    int visited[1000000];          // ❌ 지역 배열 4MB → 스택 한도를 넘으면 런타임 에러
}

int visited[1000000];              // ✅ 전역 배열은 스택이 아닌 정적 영역, 0으로 초기화됨
std::vector<int> visited2(1000000);  // ✅ 힙에 할당

지역 변수는 스택에 잡히는데, 기본 스택 크기는 Windows가 1MB, Linux가 보통 8MB라 큰 지역 배열은 로컬에서는 되고 채점 서버에서는 안 되거나 그 반대가 됩니다. 큰 배열은 전역이나 vector로 두고, 방문 여부처럼 참/거짓만 담는 큰 배열은 std::vector<bool>이나 std::bitset으로 메모리를 8분의 1로 줄일 수 있습니다. 깊이가 수십만인 DFS 재귀도 같은 이유로 스택을 넘칠 수 있어, 입력 한도가 크면 명시적 스택을 쓰는 반복문으로 바꾸는 것을 고려합니다.

구현(시뮬레이션) 문제

백준에서 알고리즘보다 조건을 빠짐없이 옮기는 능력을 보는 유형입니다. 주사위 굴리기(14499), 로봇 청소기(14503)처럼 격자 위에서 규칙대로 움직이는 문제가 대표적입니다. 이런 문제는 풀이 아이디어보다 방향 배열(dx, dy)의 순서, 회전 방향, 범위 검사를 이동 전에 하는지 후에 하는지 같은 세부 사항에서 틀리는 경우가 대부분이라, 코드를 쓰기 전에 문제의 규칙을 번호 목록으로 옮겨 적고 각 규칙을 함수 하나씩으로 구현하면 디버깅이 훨씬 쉬워집니다. 막히면 매 단계 후 격자 상태를 출력해 손으로 푼 결과와 비교합니다.

면접 당일 체크리스트

문제 이해 단계 (5분)

  • 입력 형식과 범위 확인 (N ≤ ?, 음수 가능?)
  • 출력 형식 확인 (여러 줄? 공백 구분?)
  • 예제 입력·출력 손으로 따라가 보기
  • 엣지 케이스 생각해 보기 (N=0, N=1, 중복, 최대값)

알고리즘 설계 단계 (5~10분)

  • 무식한 방법(Brute Force)의 시간복잡도 계산
  • 제한 시간 내에 가능한지 판단
  • 최적화 방법 떠올리기 (정렬? 해시맵? DP?)
  • 면접관에게 접근법 설명 (화이트보드 면접 시 필수)

코딩 단계 (15~30분)

  • 입출력 최적화 템플릿 복붙 (sync_with_stdio, cin.tie)
  • 함수·변수명 명확하게
  • 반복문 범위 확인 (< vs <=, 인덱스 0 vs 1)
  • 오버플로우 체크 (int vs long long)

테스트 단계 (5~10분)

  • 예제 입력으로 실행
  • 엣지 케이스 직접 테스트 (N=0, N=1, 최대값)
  • 시간복잡도 다시 확인

설명 단계 (면접관에게)

  • 알고리즘 접근법 설명
  • 시간복잡도·공간복잡도 언급
  • 최적화 가능한 부분 언급 (시간이 남으면)

자주 나오는 면접 질문

”시간복잡도가 어떻게 되나요?”

답변 예시:

“정렬에 O(N log N), 이후 투 포인터로 O(N)이므로, 전체 O(N log N)입니다."

"공간복잡도는요?”

답변 예시:

“입력 배열 외에 해시맵을 쓰므로 최악의 경우 O(N)입니다."

"더 최적화할 수 있나요?”

답변 예시:

“현재 O(N log N)인데, 입력이 특정 범위로 제한되어 있다면 카운팅 정렬로 O(N)까지 줄일 수 있습니다."

"엣지 케이스는 어떻게 처리하나요?”

답변 예시:

“N=0일 때는 빈 배열을 반환하며, N=1일 때는 첫 원소를 바로 반환하도록 예외 처리했습니다.”


실전 준비 로드맵

1단계: 기본 자료구조·알고리즘 복습 (1~2주)

  • 자료구조: 배열, 연결 리스트, 스택, 큐, 해시맵, 트리, 힙
  • 알고리즘: 정렬, 탐색, 재귀, DP, 그래프(BFS/DFS), 그리디

추천 자료:

  • 백준 단계별로 풀어보기
  • 프로그래머스 Level 1~2

2단계: 유형별 문제 풀이 (2~3주)

  • 정렬·탐색: 백준 10문제
  • DP: 백준 10문제 (피보나치, LIS, 배낭)
  • 그래프: BFS/DFS 각 5문제
  • 그리디: 5문제
  • 투 포인터·슬라이딩 윈도우: 5문제

3단계: 모의 면접 (1주)

  • 타이머 30분 설정하고 문제 풀기
  • 화이트보드에 손으로 써 보기 (타이핑 없이)
  • 친구·동료와 모의 면접 (설명 연습)

4단계: 기출 문제 풀이

  • 지원하는 회사의 코딩 테스트 후기 검색 (백준, 프로그래머스 등)
  • 비슷한 유형 집중 연습

면접 중 커뮤니케이션 팁

문제를 이해했는지 확인

“제가 이해한 게 맞는지 확인하고 싶은데요, 입력은 N개의 정수 배열이며, 합이 K인 두 원소의 인덱스를 반환하는 거 맞나요?”

접근법 먼저 설명

“먼저 배열을 정렬하며, 투 포인터로 양 끝에서 좁혀 가며 합을 확인하겠습니다. 시간복잡도는 O(N log N)입니다.”

막히면 힌트 요청

“지금 DP 테이블을 어떻게 정의해야 할지 고민 중인데, 힌트를 주실 수 있을까요?”

트레이드오프 언급

“해시맵을 쓰면 O(N)이지만 공간복잡도가 O(N)이고, 정렬하면 O(N log N)이지만 공간은 O(1)입니다. 어느 쪽이 나을까요?”


자주 하는 실수

입출력 최적화 안 함

대량 입출력 문제에서 sync_with_stdio(false), cin.tie(NULL) 없이 제출 → 시간 초과

int 오버플로우

int a = 1000000, b = 1000000;
int result = a * b;  // ❌ int 범위 초과 (2×10¹²)

해결:

long long result = (long long)a * b;  // ✅

배열 범위 초과

int arr[100];
for (int i = 0; i <= 100; ++i) {  // ❌ i=100은 범위 초과
    arr[i] = 0;
}

해결: i < 100 또는 vector의 at() 사용.

정렬 안 하고 이진 탐색

binary_search는 정렬된 배열에서만 작동합니다.

std::vector<int> v = {3, 1, 4};
bool found = std::binary_search(v.begin(), v.end(), 3);  // ❌ 정렬 안 됨

해결:

std::sort(v.begin(), v.end());
bool found = std::binary_search(v.begin(), v.end(), 3);  // ✅

추천 연습 플랫폼

플랫폼특징추천 대상
백준(BOJ)한국어, 단계별 문제, 다양한 난이도국내 취준생
프로그래머스한국어, 기업 기출 문제국내 기업 면접 준비
LeetCode영어, 글로벌 기업 기출 (FAANG)해외 취업, 고난도
Codeforces영어, 경진대회 스타일알고리즘 실력 향상

C++ 코딩테스트는 STL·입출력 최적화·자주 쓰는 패턴을 익히고, 백준·프로그래머스로 연습하면 됩니다. 다음으로 입출력 치트시트나 STL 알고리즘을 읽어보면 좋습니다.


자주 묻는 질문 (FAQ)

Q. C++가 Python보다 코딩 테스트에 유리한가요?

A: 문제에 따라 다릅니다.

  • 유리한 점: 실행 속도가 빠름 (시간 제한 빡빡한 문제)
  • 불리한 점: 코드가 길고, 입출력 설정이 복잡함
  • 결론: 본인이 익숙한 언어를 쓰는 것이 가장 중요합니다.

Q. bits/stdc++.h는 항상 써도 되나요?

A: 온라인 저지(백준, 프로그래머스)에서는 OK지만, 실무에서는 쓰지 않습니다. 컴파일 시간이 느리고, 이식성이 떨어집니다. 면접에서는 “코딩 테스트용 편의 헤더”라고 설명하면 됩니다.

Q. STL을 모르면 C++ 코딩 테스트는 불가능한가요?

A: 거의 불가능합니다. vector, map, sort 같은 기본 STL 없이 배열·정렬을 직접 구현하면 시간이 부족합니다. 최소한 vector, map, set, sort, find는 익혀야 합니다.

Q. 면접 중에 컴파일 에러가 나면?

A: 당황하지 말고 에러 메시지를 읽고 차근차근 고치세요. 면접관은 디버깅 능력도 평가합니다. “세미콜론을 빠뜨렸네요”라고 말하며 고치면 됩니다.


C++ 코딩 테스트 면접은 알고리즘 지식 + STL 활용 능력 + 시간복잡도 분석을 모두 평가합니다. 위 7가지 유형을 각 10문제씩 풀어 보며, 입출력 최적화 템플릿을 외워 두면 대부분의 문제에 대응할 수 있습니다. 면접 중에는 접근법을 먼저 설명하며, 엣지 케이스를 언급하면 좋은 인상을 줄 수 있습니다. 막히더라도 사고 과정을 소리 내어 말하면서 진행하세요. 면접관은 정답보다 문제 해결 과정을 보고 싶어 합니다.


같이 보면 좋은 글