Coding Test Complete Preparation Guide | From Algorithms to Practical Tips

Coding Test Complete Preparation Guide | From Algorithms to Practical Tips

이 글의 핵심

Coding test complete preparation guide with detailed explanation of essential algorithms, problem-solving strategies, and practical tips.

Introduction: Coding Tests Are All About Preparation

”I Failed Because I Didn’t Know Algorithms”

Coding tests are pattern recognition. Anyone can pass by learning frequently appearing patterns and practicing repeatedly.

What This Guide Covers:

  • Essential algorithms and data structures
  • Problem-solving patterns
  • Time management strategy
  • Language selection guide
  • Practical tips

Table of Contents

  1. Essential Algorithms
  2. Essential Data Structures
  3. Problem-Solving Patterns
  4. Time Management
  5. Language Selection
  6. Practical Tips
  7. Summary

1. Essential Algorithms

Learning Order by Priority

graph TB
    A[Coding Test Algorithms] --> B[Stage 1: Essential]
    A --> C[Stage 2: Important]
    A --> D[Stage 3: Advanced]
    
    B --> B1[Two Pointers]
    B --> B2[Sliding Window]
    B --> B3[Binary Search]
    B --> B4[BFS/DFS]
    
    C --> C1[Dynamic Programming]
    C --> C2[Greedy]
    C --> C3[Backtracking]
    
    D --> D1[Shortest Path]
    D --> D2[Topological Sort]
    D --> D3[Trie]

Stage 1: Essential Algorithms (High Frequency)

Two Pointers:

# Example: Two sum in sorted array
def two_sum(arr, target):
    left, right = 0, len(arr) - 1
    
    while left < right:
        current_sum = arr[left] + arr[right]
        if current_sum == target:
            return [left, right]
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    
    return None

# Time complexity: O(n)

Sliding Window:

# Example: Maximum sum subarray of length k
def max_sum_subarray(arr, k):
    window_sum = sum(arr[:k])
    max_sum = window_sum
    
    for i in range(k, len(arr)):
        window_sum += arr[i] - arr[i - k]
        max_sum = max(max_sum, window_sum)
    
    return max_sum

# Time complexity: O(n)

Binary Search:

# Example: Find value in sorted array
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1

# Time complexity: O(log n)

BFS/DFS (Breadth/Depth First Search):

from collections import deque

# BFS
def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)
    
    while queue:
        node = queue.popleft()
        print(node)
        
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)

# DFS (recursive)
def dfs(graph, node, visited=None):
    if visited is None:
        visited = set()
    
    visited.add(node)
    print(node)
    
    for neighbor in graph[node]:
        if neighbor not in visited:
            dfs(graph, neighbor, visited)

Stage 2: Important Algorithms

Dynamic Programming (DP):

# Example: Fibonacci sequence
def fibonacci(n):
    if n <= 1:
        return n
    
    dp = [0] * (n + 1)
    dp[1] = 1
    
    for i in range(2, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    
    return dp[n]

# Time complexity: O(n)
# Space complexity: O(n)

Greedy:

# Example: Coin change
def coin_change(coins, amount):
    coins.sort(reverse=True)
    count = 0
    
    for coin in coins:
        if amount >= coin:
            count += amount // coin
            amount %= coin
    
    return count if amount == 0 else -1

2. Essential Data Structures

Learning by Priority

PriorityData StructureFrequencyDifficulty
1ArrayVery HighEasy
2HashMapVery HighEasy
3StackHighEasy
4QueueHighEasy
5HeapMediumMedium
6TreeMediumMedium
7GraphMediumHard

Core Operations by Data Structure

Array:

# Essential operations
arr = [1, 2, 3, 4, 5]
arr.append(6)        # Add at end O(1)
arr.pop()            # Remove from end O(1)
arr.insert(0, 0)     # Add at front O(n)
arr.remove(3)        # Remove value O(n)
arr.sort()           # Sort O(n log n)

HashMap:

# Essential operations
d = {}
d['key'] = 'value'   # Insert O(1)
val = d.get('key')   # Lookup O(1)
del d['key']         # Delete O(1)
'key' in d           # Check existence O(1)

Stack:

# Stack (LIFO)
stack = []
stack.append(1)      # push
stack.append(2)
top = stack.pop()    # pop (2)

Queue:

from collections import deque

# Queue (FIFO)
queue = deque()
queue.append(1)      # enqueue
queue.append(2)
front = queue.popleft()  # dequeue (1)

Heap:

import heapq

# Min heap
heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 2)

min_val = heapq.heappop(heap)  # 1

# Max heap (use negative)
max_heap = []
heapq.heappush(max_heap, -3)
heapq.heappush(max_heap, -1)
max_val = -heapq.heappop(max_heap)  # 3

3. Problem-Solving Patterns

Pattern Recognition Flowchart

flowchart TD
    A[Read Problem] --> B{Sorted Array?}
    B -->|Yes| C[Binary Search or Two Pointers]
    B -->|No| D{Subarray/Substring?}
    D -->|Yes| E[Sliding Window]
    D -->|No| F{Graph/Tree?}
    F -->|Yes| G[BFS/DFS]
    F -->|No| H{Optimization Problem?}
    H -->|Yes| I[DP or Greedy]
    H -->|No| J[HashMap or Stack/Queue]

Examples by Pattern

Pattern 1: Two Pointers

# LeetCode 15. 3Sum
def three_sum(nums):
    nums.sort()
    result = []
    
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i-1]:
            continue
        
        left, right = i + 1, len(nums) - 1
        while left < right:
            total = nums[i] + nums[left] + nums[right]
            if total == 0:
                result.append([nums[i], nums[left], nums[right]])
                left += 1
                right -= 1
                while left < right and nums[left] == nums[left-1]:
                    left += 1
            elif total < 0:
                left += 1
            else:
                right -= 1
    
    return result

Pattern 2: Sliding Window

# LeetCode 3. Longest Substring Without Repeating Characters
def length_of_longest_substring(s):
    char_set = set()
    left = 0
    max_length = 0
    
    for right in range(len(s)):
        while s[right] in char_set:
            char_set.remove(s[left])
            left += 1
        
        char_set.add(s[right])
        max_length = max(max_length, right - left + 1)
    
    return max_length

Pattern 3: BFS

# LeetCode 102. Binary Tree Level Order Traversal
from collections import deque

def level_order(root):
    if not root:
        return []
    
    result = []
    queue = deque([root])
    
    while queue:
        level_size = len(queue)
        level = []
        
        for _ in range(level_size):
            node = queue.popleft()
            level.append(node.val)
            
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        
        result.append(level)
    
    return result

Pattern 4: Dynamic Programming

# LeetCode 70. Climbing Stairs
def climb_stairs(n):
    if n <= 2:
        return n
    
    dp = [0] * (n + 1)
    dp[1], dp[2] = 1, 2
    
    for i in range(3, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    
    return dp[n]

4. Time Management

Exam Time Allocation (2 hours, 4 problems)

Total time: 120 minutes

Problem 1 (Easy):   20 minutes
Problem 2 (Medium): 30 minutes
Problem 3 (Medium): 35 minutes
Problem 4 (Hard):   35 minutes

Buffer time: 10 minutes (review and debugging)

Problem-Solving Process

flowchart LR
    A[Read Problem 3min] --> B[Analyze Examples 2min]
    B --> C[Design Approach 5min]
    C --> D[Write Code 15min]
    D --> E[Test 3min]
    E --> F[Debug 2min]

Checklist for Each Stage:

1. Read Problem (3 min):

  • Check input format
  • Check output format
  • Check constraints (n range, time limit)
  • Identify edge cases

2. Analyze Examples (2 min):

  • Trace example input/output by hand
  • Pattern recognition
  • Think about exception cases

3. Design Approach (5 min):

  • Calculate brute force time complexity
  • Consider optimization methods
  • Select data structures
  • Write pseudocode

4. Write Code (15 min):

  • Write function signature
  • Implement core logic
  • Handle edge cases

5. Test (3 min):

  • Test with example inputs
  • Test edge cases (empty array, size 1, max size)
  • Check output format

6. Debug (2 min):

  • Check error messages
  • Print debugging
  • Fix logic errors

5. Language Selection

Pros and Cons by Language

LanguageProsConsRecommended For
PythonConcise syntax, fast implementationSlow speed (TLE possible)Most cases
C++Fast speed, STLLong code, debugging difficultyPerformance-critical problems
JavaStable, rich APIVerbose syntaxEnterprise background
JavaScriptFamiliar to web developersLack of type safetyWeb developers

1. Concise Syntax:

# Python (5 lines)
def reverse_string(s):
    return s[::-1]

# C++ (10 lines)
#include <string>
#include <algorithm>
string reverseString(string s) {
    reverse(s.begin(), s.end());
    return s;
}

2. Rich Built-in Functions:

# Sorting
arr.sort()

# Max/Min
max_val = max(arr)
min_val = min(arr)

# Sum
total = sum(arr)

# Count
from collections import Counter
count = Counter(arr)

3. Slicing:

arr = [1, 2, 3, 4, 5]
arr[1:4]    # [2, 3, 4]
arr[::-1]   # [5, 4, 3, 2, 1] (reverse)
arr[::2]    # [1, 3, 5] (every 2)

When to Use C++

When TLE (Time Limit Exceeded) Occurs:

Problem constraint: n ≤ 10^6, time limit 1 second

Python: 10^6 operations → 1 second (tight)
C++:    10^6 operations → 0.1 second (comfortable)

→ Switch to C++ if Python gets TLE

C++ STL Essentials:

#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <set>

// Vector
vector<int> v = {1, 2, 3};
v.push_back(4);

// Sort
sort(v.begin(), v.end());

// Binary search
bool found = binary_search(v.begin(), v.end(), 3);

// Priority queue (max heap)
priority_queue<int> pq;
pq.push(3);
int top = pq.top();

6. Practical Tips

Tip 1: Prepare Templates

Python Template:

# Input processing
n = int(input())
arr = list(map(int, input().split()))

# Or
import sys
input = sys.stdin.readline

# Output
print(result)

C++ Template:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    
    vector<int> arr(n);
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    
    // Logic
    
    cout << result << endl;
    
    return 0;
}

Tip 2: Time Complexity Check

Estimate time complexity from n range:

n ≤ 10:        O(n!) possible
n ≤ 20:        O(2^n) possible
n ≤ 100:       O(n³) possible
n ≤ 1,000:     O(n²) possible
n ≤ 10,000:    O(n² / 2) possible
n ≤ 100,000:   O(n log n) needed
n ≤ 1,000,000: O(n) needed
n > 1,000,000: O(log n) or O(1) needed

Tip 3: Debugging Strategy

# Print debugging
def solve(arr):
    print(f"DEBUG: arr = {arr}")  # Check input
    
    result = []
    for i in range(len(arr)):
        print(f"DEBUG: i = {i}, arr[i] = {arr[i]}")  # Check process
        result.append(arr[i] * 2)
    
    print(f"DEBUG: result = {result}")  # Check output
    return result

Tip 4: Edge Case Check

# Cases to always test
test_cases = [
    [],              # Empty array
    [1],             # Size 1
    [1, 1, 1],       # All same values
    [1, 2, 3],       # Sorted array
    [3, 2, 1],       # Reverse order
    [-1, 0, 1],      # Contains negative
    [10**9],         # Max value
]

Tip 5: Common Mistakes to Avoid

1. Off-by-one errors:

# ❌ Wrong
for i in range(len(arr) - 1):  # Misses last element

# ✅ Correct
for i in range(len(arr)):

2. Integer overflow:

# Python: No overflow (arbitrary precision)
# C++: Use long long for large numbers
long long result = (long long)a * b;

3. Modifying while iterating:

# ❌ Wrong
for item in arr:
    if condition:
        arr.remove(item)  # Modifies during iteration

# ✅ Correct
arr = [item for item in arr if not condition]

7. Summary

3-Month Study Plan

Month 1: Build Foundation

  • Array, HashMap, Stack, Queue
  • Two Pointers, Sliding Window
  • LeetCode Easy 50 problems

Month 2: Intermediate Algorithms

  • BFS/DFS, Binary Search
  • Dynamic Programming basics
  • LeetCode Medium 50 problems

Month 3: Advanced Algorithms

  • Advanced Dynamic Programming
  • Graph algorithms
  • LeetCode Medium 50 + Hard 20 problems

Study Resources

Online Judges:

Recommended Problem Sets:

  • LeetCode Top 100 Liked
  • LeetCode Blind 75
  • NeetCode 150

Next Steps

For detailed algorithm explanations, refer to these series:

  • Algorithm Series #1: Array and List
  • Algorithm Series #10: BFS/DFS
  • Algorithm Series #12: Dynamic Programming

Related Topics:

  • Time Complexity Optimization Checklist
  • Two Pointers Pattern
  • Sliding Window Pattern

Quick Study Guide

Week 1-2: Arrays, HashMap basics
Week 3-4: Two Pointers, Sliding Window
Week 5-6: Stack, Queue, BFS/DFS
Week 7-8: Binary Search, Sorting
Week 9-10: Dynamic Programming basics
Week 11-12: Advanced DP, Greedy, Backtracking

Practice Schedule

Daily routine (2-3 hours):
1. Review 1 concept (30 min)
2. Solve 2 new problems (60 min)
3. Review 1 past problem (30 min)

Weekly:
- Monday-Friday: New problems
- Saturday: Mock test (4 problems, 2 hours)
- Sunday: Review wrong answers

Keywords

Coding Test, Algorithm, Data Structure, LeetCode, Interview, Two Pointers, Sliding Window, BFS, DFS, Dynamic Programming, Binary Search, Python, C++

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3