코딩테스트 기초

1. 코딩테스트 접근법

알고리즘(Algorithm)은 문제를 해결하기 위한 절차나 방법을 말한다. 코딩 테스트나 인터뷰를 통과하기 위해서 알고리즘 공부를 어떻게 해야할까? 몇 가지 기준을 세우고 진행하는 게 좋다.

  • 초급자: 2~3일

  • 중급자: 2~3시간

  • 고급자: 20~30분

자신이 초급자일 때는 2일 간 고민해보는 것도 좋지만, 고급자인데도 2일을 고민하는 건 시간 낭비일 수 있다. 문제를 풀기 위해 적절한 알고리즘을 찾아내는 능력을 기르는 게 핵심이다. 알고리즘 문제 풀이 능력을 기르기 위해선 다양한 알고리즘의 특징을 알고 문제 풀이를 통해 그 알고리즘으로 문제를 풀 수 있는 이유를 생각해봐야 한다.

2. 효율성과 최적화

무한대의 메모리와 시간이 있으면 어떤 풀이 방법이든 정답이 될 수 있다. 그러나 현실에서 자원은 유한하므로 효율성을 고려해서 풀이를 작성해야 한다. 일반적으로 프로그램 성능을 위해 가장 먼저 살펴보는 건 수행 시간이다.

2.1. 시간 복잡도

시간 복잡도(Time Complexity)는 문제의 크기를 측정하기 위한 방법이다. 시간 복잡도는 빅 오 표기법(Big-O notation)으로 표현한다. 예를 들어 입력값을 받아 1부터 N까지의 합을 계산한다고 생각해보자.

class BigONotation {
    public static void main(String[] args) {
        int n;
        int sum = 0;

        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        sc.close();

        for (int i=1; i<=n; i++) {
            sum += i;
        }

        System.out.println(sum);
    }
}

더하기를 N번 반복하므로 시간 복잡도는 O(N)O(N)이다. 만일 1부터 N까지의 합을 구하는 계산을 N번 반복하면 어떻게 될까?

O(N)O(N)을 N번 반복하므로 시간 복잡도는 O(N2)O(N^{2})이 된다. 빅 오 표기법에서 상수는 복잡도에 미치는 영향이 미미하므로 표기하지 않는다.

실제 수행 시간?

1억의 데이터를 처리하는데 걸리는 시간은 대략 1초이다.

2.2. 메모리

일반적으로 메모리에서 많은 공간을 차지하는 건 배열이다. 배열은 배열의 크기*자료형의 크기만큼 공간을 사용한다.

3. 입출력

프로그래밍 언어는 다양한 입력 방법을 제공한다. 입력 방법에 따라 속도 차이가 발생하므로 이를 감안해서 적절한 입출력 방식으로 풀이를 작성하는게 좋다.

3.1. 입력 속도 비교

순위
언어
입력 방법
평균(초)

1

C11

mmap

0.043

2

C11

fread

0.0799

3

C11

getchar

0.3496

4

C++17

ios_base::sync_with_stdio(false); cin.tie(NULL);

0.5938

5

C++17

ios_base::sync_with_stdio(false);

0.6348

6

java

BufferedReader, Integer.parseInt

0.6585

7

C11

scanf

0.9206

8

PyPy

int(sys.stdin.readline())

0.9229

9

PyPy

map(int,os.read(0, 100000000).split('\n'))

1.1169

10

PyPy3

map(int,os.read(0, 100000000).decode('utf-8').split('\n'))

1.5408

11

PyPy

int(raw_input())

1.925

12

C++17

cin.tie(NULL);

2.059

13

C++17

cin

2.1742

14

C# 6.0

int.Parse(Console.ReadLine())

2.9635

15

Python 3

map(int,os.read(0, 100000000).decode('utf-8').split('\n'))

4.4033

16

Python 3

int(sys.stdin.readline())

4.4394

17

Java

Scanner

4.8448

18

Python 2

map(int,os.read(0, 100000000).split('\n'))

4.8553

19

Python 2

int(sys.stdin.readline())

5.7471

20

PyPy3

int(sys.stdin.readline())

6.6291

21

Python 2

int(raw_input())

8.9765

22

Python 3

int(input())

12.4443

23

PyPy3

int(input())

17.3772

24

Python 2

input()

37.7823

25

PyPy

input()

110.3676

3.2. 출력 속도 비교

순위
언어
출력 방법
평균(초)

1

C11

fwrite

0.4423

2

C++17

ios_base::sync_with_stdio(false); cout << i << '\n';

0.827

3

C++17

ios_base::sync_with_stdio(false); cout.tie(NULL); cout << i << '\n';

0.8272

4

C++17

printf("%d\n",i);

0.8614

5

C11

printf("%d\n",i);

0.9118

6

C++17

cout << i << '\n';

0.9229

7

Java

BufferedWriter, bf.write(i + "\n");

0.9581

8

PyPy

for i in xrange(1,n+1): sys.stdout.write(str(i)+'\n')

0.9847

9

C++17

s += to_string(i) + '\n';를 이용해 문자열 하나로 만든 다음, 마지막에 cout << s << '\n';

1.1507

10

Java

StringBuilder를 이용해 문자열 하나로 만든 다음, System.out.println(sb);

1.1881

11

Java

BufferedWriter, bf.write(Integer.toString(i)); bf.newLine();

1.2556

12

PyPy3

for i in range(1,n+1): sys.stdout.write(str(i)+'\n')

1.3722

13

PyPy

print '\n'.join(map(str,xrange(1,n+1)))

1.3738

14

PyPy

sys.stdout.write('\n'.join(map(str,xrange(1,n+1))))

1.3772

15

PyPy

for i in xrange(1,n+1): print i

1.4968

16

Python 2

print '\n'.join(map(str,xrange(1,n+1)))

1.7621

17

Python 2

sys.stdout.write('\n'.join(map(str,xrange(1,n+1))))

1.7658

18

Java

PrintWriter

1.954

19

Python 3

print('\n'.join(map(str,range(1,n+1))))

2.3312

20

Python 3

sys.stdout.write('\n'.join(map(str,range(1,n+1))))

2.337

21

PyPy

sys.stdout.write(''.join(str(i)+'\n' for i in xrange(1,n+1)))

2.3935

22

PyPy

print ''.join(str(i)+'\n' for i in xrange(1,n+1))

2.3974

23

Python 2

sys.stdout.write(''.join(str(i)+'\n' for i in xrange(1,n+1)))

2.536

24

Python 2

print ''.join(str(i)+'\n' for i in xrange(1,n+1))

2.5372

25

PyPy3

for i in range(1,n+1): print(i)

3.051

26

Python 2

for i in xrange(1,n+1): print i

3.069

27

C# 6.0

StreamWriter

3.0959

28

PyPy3

sys.stdout.write('\n'.join(map(str,range(1,n+1))))

3.5625

29

PyPy3

print('\n'.join(map(str,range(1,n+1))))

3.566

30

Python 3

sys.stdout.write(''.join(str(i)+'\n' for i in range(1,n+1)))

3.6766

31

Python 3

print(''.join(str(i)+'\n' for i in range(1,n+1)))

3.6836

32

PyPy3

print(''.join(str(i)+'\n' for i in range(1,n+1)))

3.8326

33

PyPy3

sys.stdout.write(''.join(str(i)+'\n' for i in range(1,n+1)))

3.8339

34

C# 6.0

StringBuilder를 이용해 문자열 하나로 만든 다음, Console.Write(sb);

3.8562

35

Python 2

for i in xrange(1,n+1): sys.stdout.write(str(i)+'\n')

4.3475

36

Python 3

for i in range(1,n+1): sys.stdout.write(str(i)+'\n')

5.3699

37

Python 3

for i in range(1,n+1): print(i)

5.8186

38

PyPy

for i in xrange(1,n+1): os.write(1,str(i)+'\n')

10.4553

39

C++17

cout << i << endl;

11.5322

40

PyPy3

for i in range(1,n+1): os.write(1,(str(i)+'\n').encode('utf-8'))

12.0509

41

Python 2

for i in xrange(1,n+1): os.write(1,str(i)+'\n')

14.8269

42

Python 3

for i in range(1,n+1): os.write(1,(str(i)+'\n').encode('utf-8'))

18.2189

43

Java

System.out.println(i);

30.013

44

C# 6.0

Console.WriteLine(i);

30.1438

3.3. 입력 속도 향상

C++의 cin/cout은 scanf/prinf보다 느리다. 이 경우에 아래 코드를 추가하면 성능을 향상시킬 수 있다.

다만 이 방법은 편법이므로 주의사항을 지켜야 한다.

  • scanf/prinf와 섞어서 사용하지 말 것

  • 싱글 스레드 환경에서만 사용할 것

자바의 경우 입력이 많을 때 Scanner 대신 BufferReader를 사용해서 속도를 높일 수 있다. 출력이 많은 경우에는 BufferWriter를 사용하거나 StringBuilder를 사용해서 한 번만 출력할 수 있다.

참고 자료

Last updated