프로그래밍 문제를 해결하는 데에는 여러가지 방법이 있다. 어떤 방법이 다른 방법보다 나은지(어떤 방법을 선택할지) 어떻게 알 수 있을까?



알고리즘이 어떤 문제를 해결하는 데 걸리는 시간을 시간복잡도(Time complexity)라고 하고 주로 빅오표기법(Big O notation)을 이용해 나타낸다. 입력값이 n개 일 때 걸리는 시간을 비교해 알고리즘의 효율성을 표현하기 위한 방식이다. 이 때 n의 값은 충분히 크다고 가정한다.



n의 값에 따른 알고리즘의 시간복잡도는 다음과 같다.




O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ) < O(n!) < O(nⁿ)




이해를 돕기 위해 예시를 보자. 다음 코드는 크기가 n인 정수배열에서 0보다 작은 값이 있으면 true, 없으면 false를 반환한다. 시간복잡도를 계산해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public boolean hasNegativeNumber(int array[]){
 
    if(array==null){
        return false;
    } 
 
    for(int i=0 ; i<array.length ; i++){
        if(array[i]<0){
            return true;
        }
    }
    return false;
}
 
cs


배열을 순서대로 탐색하므로 만약 array[0]의 값이 음수라면 시작하자마자 결과가 나오겠지만(best case) 음수가 배열의 맨 마지막에 있다면array[n]까지 탐색해야하므로(worst case) n만큼의 시간이 걸린다. 하지만 아무리 최악의 경우라도 O(n)보다 시간이 더 걸리지는 않는다. 위의 코드의 시간복잡도는 O(n)이다.




두번째로는 정수배열과 목표값을 입력으로 받아 배열 요소의 값의 합이 목표값과 일치하는 인덱스를 찾아 반환하는 코드를 보자.


1
2
3
4
5
6
7
8
9
10
public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
cs


이중 for문을 사용하므로 최대 n(n-1)/2만큼의 시간이 걸린다. 우리는 n이 충분히 큰 수라고 가정하기 때문에 가장 큰 항에서 상수는 무시하고 따라서 이 경우 시간복잡도는 O(n²)이다.



Big O notation은 실행시간이 꼭 그만큼 걸린다기 보다는 실행시간의 최댓값은 이정도이기때문에 '아무리 최악의 케이스여도 이정도 속도까지는 보장한다'라고 이해하면 된다.





오늘 소개할 사이트는 LeetCode.com 이다. 국내에도 코딩테스트 연습 사이트는 많지만 영어로 된 LeetCode를 추천한다.

한국에서만 일할 예정이라면 굳이 영어를 하지 않아도 괜찮다 생각 할 수도 있다. 하지만 영어로 구글링을 할 줄 알면 접할 수 있는 정보량에 차이가 있다. 이제 막 개발을 시작해서 초보적인 수준의 공부를 할 때에는 큰 차이가 없을 수도 있지만 언젠가 한국어 자료들만으로는 해결이 어려운 문제들을 접하게 될 것이다. 평소에 영어로 된 프로그래밍 컨텐츠들을 자주 접하고 영문 자료를 읽는데 익숙해 질 수 있도록 하자.




LeetCode를 이용하려면 회원가입을 해야 한다. 무료로 이용할 수 있으니 Create Account를 눌러 가입한다.





Mock 카테고리에 들어가면 모의인터뷰를 할 수 있다. 코딩테스트 뿐만 아니라 인성면접에 대한내용들도 있다. 이건 프리미엄(유료) 멤버에게만 공개되는데 아직 여기까지 할 필요는 없으니 넘어간다.





우리가 볼 것은 Problem카테고리이다. 문제의 난이도는 Easy/Medium/High로 나뉘어져 있으니 원하는 수준에 맞게 문제를 풀면 된다.





문제를 선택하고 원하는 언어를 고르면 자동으로 클래스명,파라미터,리턴값 등을 정해준다.

코드를 다 작성하고 난 후에는 오른쪽 하단의 ▶Run Code를 눌러 돌려볼 수 있다. 입력값을 바꿔 가면서 테스트 해 보고 완료되면 Submit버튼을 눌러 제출한다.





Submit을 하고 나면 내 코드에 대한 평가가 나온다. 같은 코드도 돌릴 때마다 차이가 약간 있다. 여러번 돌려서 시간의 평균 값을 내는게 아니라 한번 돌린 결과로 나오는 듯 하니 크게 신경쓰지는 않아도 된다. 어쨌든 시간이 적게 걸릴수록, 메모리를 적게 쓸수록 좋은 코드다.





Solution탭에서 해결법을 볼 수 있다. 내 코드의 속도가 너무 느리거나 메모리를 많이 썼다면 다른 효율적인 방법이 있는지 읽어본다.





Contest탭에서는 매주 전세계 개발자들이 참여하는 코딩콘테스트가 열리니 참여가능하다.

+ Recent posts