java 피보나치 수열을 실현하는 3가지 방법

우선 이걸 왜 썼는지 말해 보세요. 이것은 완전히 알리바바 면접에서 일어난 참혹한 피사건입니다.면접을 보러 갔을 때 면접 전날 밤 11시에야 알리바바 지정 면접 도시에 도착했기 때문에 여관을 찾아 묵는 시간이 거의 1시가 넘었고 게다가 밤에 잠을 전혀 자지 못해 다음날 면접 효과가 좋지 않았다(일자리를 찾고 있는 새우들에게 비극을 주지 말고 미리 준비를 하는 것이 중요하다).면접이 한 시간 넘게 진행되었습니다 (면접이 끝나고 돌아갈 때 거의 걸어서 잠이 들 것 같습니다. 슬프다!!!),면접이 곧 끝날 때 면접관이 물어본 나의 문제는 바로 페포나 서수열에 관한 것이다. 당시 머리는 완전히 엉망이었다. 세 가지 변수를 설정하거나List로 먼저 초기화해야 한다는 것만 알았다. for순환을 쓸 때 머리는 정말 엉망진창이었다. 더 이상 엉망진창으로 쓸 수 없었다. 마지막에 면접관의 유도로 아래의 첫 번째 방식을 쓸 수밖에 없었다.현재로서는 알리바바가 전체 응용의 구조를 거칠게 구축했을 뿐이다. 정말 변혁하고 금을 캐는 황금기(능력이 있는 대하는 서둘러 가라). 알리바바의 99퍼센트의 데이터는 모두 중요한 데이터이기 때문에 바이두와 같은 주요 검색의 거두인 99퍼센트의 데이터는 모두 쓰레기이다. 데이터 분석에 있어 알리바바는 상대방이 파악한 다양한 사용자의 상세한 데이터를 통해 분석할 수 있다.사용자의 취향과 수요를 더욱 정확하게 파악하고 정확한 추측과 정확한 광고 추측에 더욱 좋은 서비스를 제공할 수 있다.텐센트의 미래 꿈이 사용자 생활의 수전기가 된다면 아리가 실현할 수 있는 미래 꿈은 사용자의 의식주에 수전기 등을 대리하는 것이다. O(___) O~는 본론으로 넘어가자.우수한 알고리즘 디자이너에게 프로그램 기능 주체가 실현되는 토대에서 두 가지에 관심을 가지는 것이 없다. 하나는 알고리즘을 설계하는 시간 복잡도이고 하나는 공간 복잡도(말하자면 한 프로그램을 실행하는 데 사용하는 시간과 차지하는 메모리 공간)이다.서로 다른 응용 장면을 토대로 일반적으로 지혜로운 알고리즘 디자이너들은 시간과 공간 두 개의 상대적으로 모순되는 자원에서 균형점을 찾는다. 예를 들어 실시간 요구가 높은 시스템은 공간 자원으로 시간을 바꾸거나 자주 사용하는 대상에 메모리를 상주시켜 응답 시간을 높인다. (캐시 기술과 현재 유행하는 NoSQL의 대부분은 메모리 데이터베이스이다.메모리 자원이 비교적 귀중한 삽입식 시스템의 경우 일반적으로 시간적 지연으로 시간을 바꾼다.다음은 페포나 서열 세 개의 실현을 통해 어떻게 하면 실제 응용 장면에 진정으로 부합되는 우수한 알고리즘을 설계할 수 있는지 설명한다. 먼저 페포나 서열을 말한다. 문자적으로 말하자면 페포나 서열은 0과 1로 시작하고 그 후의 페포나 서열은 이전의 두 수에 더해진다. 수열 형식은 다음과 같다. 0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,.........수학적으로 귀속적인 방법으로 정의된다: F_0=0F_1=1F_n = F_{n-1}+ F_{n-2}
실현 수요: 입력 번호 n은 대응하는 페포나 서수 프로그램으로 되돌아와 1― 함수 자동 교체

/**
  *
  * @Title: fnType1
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int
  * @throws Exception
  */
 public int fnType1(int n)throws Exception{
  if(n==0){
   return 0;
  }else if(n==1||n==2){
   return 1;
  }else if(n>2){
   int temp=fnType1(n-1)+fnType1(n-2);
   if(temp<0){
    throw new Exception("Invalid value for int type, too larage");
   }else{
    return temp;
   }
  }else{
   throw new Exception("IllegalArgument value for n,please enter n>=0 ");
  }
 }
이러한 방식의 단점: 대량의 교체가 창고 공간을 끊임없이 소모한다(웹 개발 디버깅과 유지보수를 하는 사람들은 모두 서버 창고 자원의 소중함을 알아야 한다. 만약에 대량의 합병 호출이 교체되어 서버 창고 자원을 회수하지 못하고 웹 서버가 붕괴된다), 효율이 낮고 편지의 자폐성이 비교적 약하다(우수한 인터페이스는 입력과 출력에 발생할 수 있는 오류 정보를 포착하고 명확한 처리 결과를 제공해야 한다).오류가 발생하기 쉽고 디버깅이 어렵기 때문에 실제 응용에서 이런 방식을 사용하는 것을 권장하지 않으며 사용 시 교체 횟수도 3회를 초과해서는 안 된다.프로그램 실현 2 - 시간 교환 공간

/**
  *
  * @Title: fnType2
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int (n<0 return -1,beyond max int size return -2)
  * @throws
  */
 public int fnType2(int n){
  int result=-1;
  int temp1=0;
  int temp2=1;
  for(int index=0;index<=n;index++){
   if(index==0){
    result=temp1;
   }else if(index==1){
    result=temp2;
   }else{
    result=temp1+temp2;
    if(result<0){
     result=-2;
     break;
    }
    temp1=temp2;
    temp2=result;
   }
  }
  return result;
 }
이 방법은 주로 장면 1: 대상이나 변수에 대한 사용 횟수가 비교적 적고 한 번 사용한 후에 다시 사용하지 않는 장면에 사용된다.사용 장면2: 메모리 자원이 비교적 희소한 실시간 요구가 높지 않은 삽입식 시스템 설계에서 이런 방식을 많이 사용한다.프로그램 실현 3 – 공간 교환 시간

 private static List<Integer> fnData=new ArrayList<Integer>();
 private static final int maxSize=50000;
 /**
  *
  * @Title: setFnData
  * @Description: TODO
  * @param    
  * @return void
  * @throws
  */
 private static  void setFnData(){
  int result=-1;
  int temp1=0;
  int temp2=1;
  for(int index=0;index<=maxSize;index++){
   if(index==0){
    result=temp1;
   }else if(index==1){
    result=temp2;
   }else{
    result=temp1+temp2;
    if(result<0){
     result=-2;
     break;
    }
    temp1=temp2;
    temp2=result;
   }
   fnData.add(result);
  }
 }
 /**
  *
  * @Title: getFnData
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int <span style="font-family: sans-serif;">(n beyond fnData.size() and n<0 return -1)</span>
  * @throws
  */
 public int getFnData(int n){
  if(fnData.size()==0){
   setFnData();
  }
  if(fnData.size()>n&&n>=0){
   return fnData.get(n);
  }else{
   return -1;
  }
 }
이 방법은 일반적으로 프로그램이 실행되는 전체 생명 주기에 대상이나 변수가 존재하거나 빈번하게 호출되는 장면에 사용된다. 예를 들어 외부 웹 서비스 인터페이스 호출, 추상적인 지속화 층, 자주 사용하는 프로필 파라미터 불러오기 등 테스트 용례:

package com.dbc.yangg.swing.test;

import java.util.ArrayList;
import java.util.List;

/**
 * n
 * @ClassName: Init
 * @Description: TODO
 * @author [email protected]
 * @date 2014 1 10 7:52:13
 *
 */
public class Init {
 /**
  *
  * @Title: fnType1
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int
  * @throws Exception
  */
 public int fnType1(int n)throws Exception{
  if(n==0){
   return 0;
  }else if(n==1||n==2){
   return 1;
  }else if(n>2){
   int temp=fnType1(n-1)+fnType1(n-2);
   if(temp<0){
    throw new Exception("Invalid value for int type, too larage");
   }else{
    return temp;
   }
  }else{
   throw new Exception("IllegalArgument value for n,please enter n>=0 ");
  }
 }
 /**
  *
  * @Title: fnType2
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int (n<0 return -1,beyond max int size return -2)
  * @throws
  */
 public int fnType2(int n){
  int result=-1;
  int temp1=0;
  int temp2=1;
  for(int index=0;index<=n;index++){
   if(index==0){
    result=temp1;
   }else if(index==1){
    result=temp2;
   }else{
    result=temp1+temp2;
    if(result<0){
     result=-2;
     break;
    }
    temp1=temp2;
    temp2=result;
   }
  }
  return result;
 }
 private static List<Integer> fnData=new ArrayList<Integer>();
 private static final int maxSize=50000;
 /**
  *
  * @Title: setFnData
  * @Description: TODO
  * @param    
  * @return void
  * @throws
  */
 private static  void setFnData(){
  int result=-1;
  int temp1=0;
  int temp2=1;
  for(int index=0;index<=maxSize;index++){
   if(index==0){
    result=temp1;
   }else if(index==1){
    result=temp2;
   }else{
    result=temp1+temp2;
    if(result<0){
     result=-2;
     break;
    }
    temp1=temp2;
    temp2=result;
   }
   fnData.add(result);
  }
 }
 /**
  *
  * @Title: getFnData
  * @Description: TODO
  * @param @param n
  * @param @return   
  * @return int (n beyond fnData.size() and n<0 return -1)
  * @throws
  */
 public int getFnData(int n){
  if(fnData.size()==0){
   setFnData();
  }
  if(fnData.size()>n&&n>=0){
   return fnData.get(n);
  }else{
   return -1;
  }
 }
 /**
  *
  * @Title: main
  * @Description: TODO
  * @param @param argv   
  * @return void
  * @throws
  */
 public static void main(String[] argv){
  Init init=new Init();
  int n=46;
  try {
   System.out.println("Type1="+init.fnType1(n));
  } catch (Exception e) {
   // TODO Auto-generated catch block
   System.out.println(e.getMessage());
  }
  System.out.println("Type2="+init.fnType2(n));
  System.out.println("Type3="+init.getFnData(n));
 }
}

출력 결과:

Type1=1836311903 
Type2=1836311903 
Type3=1836311903 
알고리즘 디자인에 대해 맹목적으로 개념을 따르지 마라. 개념은 죽고 사람은 산다(이 시대에crazyman이 필요한 시대에 규칙을 따르는 것보다 아이디어가 우세하다). 구체적인 응용 장면을 결합해야만 우수한 알고리즘과 구조를 설계할 수 있다.개인적으로 우수한 데이터 구조 디자인은 알고리즘 디자인의 복잡도를 간소화하고 코드의 가독성, 프로그램의 확장성과 집행 효율을 높일 수 있다고 생각한다.다시 한 번 말씀드리지만 수요 분석을 할 때 세 가지 원칙을 따라야 합니다. 1.사용자의 각도와 사고방식 분석;2. 사용자가 말한 것이 반드시 그들이 진정으로 원하는 것은 아니다.3. 사용자의 말이 꼭 맞는 것은 아니다.프로그램 개발은 원칙에 따른다. 자신의 품위를 적극적으로 향상시키고 사용자의 사용 각도에 서서 장면 분석 기능을 사용한다.예를 들어 백엔드 인터페이스 개발을 하면 당신의 사용자는 인터페이스 호출자입니다. 인터페이스 기능이 무엇인지, 사용자가 어떤 상황에서 호출될지, 파라미터를 전송하면 어떤 이상을 초래할 수 있는지, 당신의 인터페이스 실현 과정에서 어떤 이상이 나타날 수 있는지, 그리고 발생할 수 있는 이상을 포획하여 명확한 출력, 좋은 함수 자폐성을 고려해야 합니다.만약 당신이 프론트 데스크톱을 한다면 업무 실현을 확보하는 토대에서 사용자의 사용 습관 등 측면에서 자신을 사용자로 삼아 UI를 설계해야 한다.재미있죠? 수요, 개발이 많으면 자연히 O(____)O~를 알 수 있어요.

좋은 웹페이지 즐겨찾기