문제는 간단했다.
n을 1과 2로 이루어진 합으로 계산할 때 과연 몇가지 경우의수가 가능한가를 구하면 된다.
처음에는 규칙을 찾아보니 이런식의 규칙을 발견해서 이를 토대로 조합 함수를 만들고 다 더해보려했다.
int climbStairs(int n){
  int a=n, res=0, loop=howMany(n);
  for (int i=0;i<=loop;){
    res+=combinations(a--,i++);
  }
  return res;
}
int combinations(int n, int r){
  int denominator=factorial(n-r)*factorial(r);
  int numerator=factorial(n);
  return numerator/denominator;
}
int factorial(int k){
  if (k==0){
    return 1;
  }
  int res=1;
  for (int i=k;i>1;i--){
    res*=i;
  }
  return res;
}
int howMany(int n){
  if (n==1){
    return 0;
  }
  if (n%2==0){
    return n/2;
  }
  else{
    return (n/2)+1;
  }
}
그러나 이 코드는 factorial 과정에서 자료형 최대 범위를 넘어가는 것이 자명하다.
전부다 계산하지 않고 뭔가 수식을 최적화할 수 있는 방법이 있나??
그런데 각 n마다 최종 계산 결과를 살펴보니 피보나치 수열과같은 규칙이 보였고, 일반항도 세울 수 있었다.
그리고 이를 재귀함수로 작성했다.
int climbStairs(int n){
  if (n<=3){
    return n;
  }
  else{
    return climbStairs(n-1)+climbStairs(n-2);
  }
}
그러나 n이 커지자 시간초과가 발생한다.
예를 들어, n=35일때 climb(34)와 climb(33)이 호출되면서 많은 겹치는 호출들이 발생한다.
원래는 여기서 DP나 Memoization을 떠올렸지만 다음 방법이 훨씬 간단해서 하지 않았다.
생각을 바꿔서 앞에서부터 해보자. 2+3=5 그리고 5+x=y, x+y=z ... 이런식으로
idx는 n까지 점점커진다. pre1은  pre2는 를 의미한다.
n=4일때를 예를 들어보자. pre1과 pre2가 각각 3과 2 이므로 두 값을 더한 5가 답이된다.
n=5일때는? 앞서 n=4일때 구한 5가 지금의 pre1이 되고 n=4일때 pre1이 지금의 pre2가 되어 5+3=8이 된다.
int climbStairs(int n){
  if (n<=3){
    return n;
  }
  else{
    int idx=4, pre1=3, pre2=2;
    while (idx++<=n){
      int tmp=pre1;
      pre1=pre1+pre2;
      pre2=tmp;
    }
    return pre1;
  }
}

알고리즘은 동일.
중요한건 저 규칙이 왜 그런지 이해하는 것. (오른쪽 계단 그림 참고) n번째 계단을 오르려면 n-1번째 계단에서 +1하거나, n-2번째 계단에서 +2하는 경우의 수밖에 없기 때문이다!
잘못된 부분 지적 및 질문해주시면 감사하겠습니다