-
[TDD] 피보나치수열IT 발자취.../알고리즘 2018. 12. 9. 00:34
안녕하세요.
초급 개발자의 TDD 공부기입니다.
TDD 공부 할 겸? 알고리즘 공부를 해보기 위해
TDD를 이용한 알고리즘 학습을 주제로 포스팅을 시작해보려합니다.일단 키보드로 두들기면 익혀보기로 했습니다.
환경: java8, junit4
github 주소 : https://github.com/gintire/algorithm/tree/master/algorithm
먼저 다음과 같이 Fibonacci 클래스와 FibonacciTest 클래스를 만들어줍니다.
Step /src/main/java/Fibonacci.java
/src/test/java/FibonacciTest.java
결과
Step1 2. fib함수가 0을 대입했을 경우 0을 반환하는건 확실하므로 먼저 상수 0을 반환합니다.
1. 먼저, 다음과 같이 테스트 케이스를 작성합니다.
- TC > Fibonacci 클래스의 fib함수에서 (0)을 삽입하였을 경우 0이 나온다.
- 현재 fib 함수를 만들지 않았다면, 빨간줄이 그어질 것입니다.
(네. 저는 미리 만들어놔서 빨간줄이 없네요...)
3. Alt + shift + x -> t를 누르면 테스트 케이스가 돌아갑니다.
- 네!!! 성공적으로 첫번째 테스트를 통과하였습니다.
Step2
2. 0을 특별한 경우로 다루는 방법을 씁니다.
1. 두번째, 피보나치의 두번째 수 1을 넣으면 1이 반환 되는 TC를 추가합니다.
- 0을 넣든 1을 넣든 Step1의 Fibonacci.fib(n)은 상수 0을 반환하므로 새로 생성한 TC를 돌리면 아마 틀렸다고 나올것입니다.
- 네... 하나하나 캡쳐하긴 너무 많아서 fib(n)을 수정후 TC를 돌렸습니다.
3. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
- 성공적으로 두번째 테스트도 통과하였습니다.
Step3
1. 테스트 케이스를 아래로 중복으로 생성시켜주는게 성가시게 느껴집니다.
- 입력과 예상값으로 구성된 테이블을 통해 테스트가 돌아가게 하면 단언의 공통 구조를 추출할 수 있습니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
- 정상적으로 동작합니다.
Step4
1. 테스트 케이스를 하나 더 추가해봅니다.
- 운이 좋게 피보나치 수열은 0,1,1,2,3.... 이렇게 늘어나기 때문에 다음 TC 도 정상적으로 돌아 갈것 같습니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
- 잘 동작합니다.
Step5
1. 4번째 테스트 케이스를 추가해본니다.
- 역시 이제는 실패할것 같은 기분이듭니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
- 실패 !! 이유를 보면 결과는 2를 예상했지만 1을 반환했다고 합니다. 당연, fib(n)은 0이 아니면 1을 반환하게 되있습니다.
Step6
1. 두번째 예외사항을 줍니다.
- 이전의 전략 ( 더 작은 입력값을 특별한 경우로 다루는 것)을 똑같이 적용하여 다음과 같이 작성합니다.
- 일반화를 하면 2는 실제로 1+1을 의미합니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
성공적으로 돌아갑니다!!
Step7
1. 첫번째 1은 fib(n-1)로 볼 수 있습니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
성공적으로 돌아갑니다.
Step8
1. 두번째 1은 fib(n-2)로 볼 수 있습니다.
2. Alt + shift +x -> t를 누르면 테스트 케이스가 돌아갑니다.
성공적으로 돌아갑니다!!!!!!
흠 ... 켄트 백님의 TDD를 사용해서 알고리즘을 푸는 것을 따라 해보았습니다.
느낀점은 구현을 할 때 TDD를 사용하면,
시간복잡도를 감안하여 코딩하기엔 부적절하지 않나 생각됩니다.
현재 풀이법으로 구현은 가능하지만 시간복잡도가 O(n^2)입니다.
순환적인 피보나치 수열을 하나의 함수 호출이 두개의 함수호출로 나뉘어지는 바이너리 트리 형태입니다.
즉, fib(n)
/ |
fib(n-1) fib(n-2)
/ | / |
fib(n-2) fib(n-3) fib(n-3) fib(n-4)
위와 같이 높이가 n일 경우 바이너리 트리의 총 노드 수는 2^n -1 개입니다.
위의 예는, 높이가 3일 때 노드가 총 7개 , 이것은 2^3 -1과 같습니다.
따라서 fib(n) 의 시간 복잡도는 O(2^n -1 ) = O(2^n)입니다.
피보나치의 경우 작은 문제로 나누었을 때,
큰문제와 작은 문제가 상호 작용할 수 있기 때문에
메모이제이션을 사용한 DP를 사용하면
O(n)으로 풀 수 있습니다.
TDD를 더해봐야 알겠지만 ...
이렇게 풀면 제한 시간내에 통과를 할 수 있을지는 의문입니다 ?^^
처음 쓰는거라 어떻게 구성을 해야할 지 잘모르겠네요 ㅎㅎㅎ
앞으로 더 나아지는 모습으로 돌아오겠습니다.
- 켄트 백 [본문으로]
'IT 발자취... > 알고리즘' 카테고리의 다른 글
[자료구조] 완전 이진 트리를 배열로 만들 경우 크기 계산 (0) 2019.08.03 [알고리즘] 세그먼트 트리 ( Segment Tree ) (1) 2019.08.03 [알고리즘] 구간 합 구하기 ( 백준 2042 ) (0) 2019.08.03 [알고리즘] 다익스트라 알고리즘 (최단 경로 알고리즘) - 이론편 (0) 2019.07.24 [알고리즘] 큐빙 (0) 2018.12.12 댓글