java完成斐波那契數列的3種辦法。本站提示廣大學習愛好者:(java完成斐波那契數列的3種辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是java完成斐波那契數列的3種辦法正文
先說說為何寫這個吧,這個完整是由去阿裡巴巴面試惹起的一次慘目忍睹的血案。去面試的時刻,因為面試前天早晨11點鐘才到阿裡巴巴指定面試城市,找到旅店住下根本都1點多,加上早晨完整沒有睡好,直接招致第二天面試後果很欠好(關於那些正在找任務的年夜蝦們不要向小蝦一下喜劇,提早做好預備照樣很主要滴),面試年夜概停止了一個多小時(面試停止歸去的時刻根本走路都快睡著了,悲催!!),面試快停止的時刻面試官問的我成績就是關於費波那西數列,其時腦筋完整漿糊,只曉得要設置三個變量或許用List先初始化,當寫到for輪回的時刻,腦殼的確漿糊的不克不及再漿糊了,沒寫出來,最初只能在面試官的步步引誘下寫出了上面的第一種方法,很不該該呀;從如今來看阿裡只是把粗心大意的把全部運用的框架搭建起來了,真是變更、挖金的黃金期(有才能的年夜蝦趕忙去),究竟阿裡巴巴手中99%的數據都是主要數據而向百度這類的主推搜刮的巨子99%數據都是渣滓比擬,關於數據剖析來講,阿裡更能經由過程敵手中控制的多種多樣的用戶具體數據停止剖析,更能准確定位用戶的咀嚼及需求,為准確推送和精准告白推送供給更好的辦事。假如說騰訊將來的妄想是做用戶生涯中的水電氣的話,那阿裡能夠完成的將來妄想就是用戶的衣食住行外加代收水電氣等等,O(∩_∩)O~照樣轉入正題吧。
關於優良的算法設計員來講,在法式功效主體完成的基本上不過關懷兩個器械,一個設盤算法的時光龐雜度,一個是空間龐雜度(說白了就是履行一個法式所用的時光和占用的內存空間);在依據分歧的運用場景的基本上,普通充斥聰明的算法設計師會在時光和空間兩個絕對抵觸的資本中追求到均衡點,照實時性請求高的體系普通會以空間資本換取時光或許關於經常使用到的對象普通會常駐內存以進步呼應時光(緩存技巧和如今比擬風行NoSQL中年夜多是內存數據庫都是如斯),關於內存資本比擬名貴的嵌入式體系而言普通會以時光上的延遲來換取時光。
上面從費波那西數列三個完成下去說說,怎樣能力真正設計出真正相符現實運用場景的優良算法
起首說說費波那西數列:
從文字上說,費波那西數列由0和1開端,以後的費波那西系數就由之前的兩數相加,數列情勢以下:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,………………
在數學上,是以遞歸的辦法來界說:
F_0=0
F_1=1
F_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 ");
}
}
此種方法缺陷:年夜量迭代赓續消費棧空間(弄web開辟調試保護的都應當曉得辦事器棧資本的寶貴,假如年夜量並發挪用迭代招致辦事器棧資本遲遲得不到收受接管,而招致web辦事器瓦解),效力底,函數自閉性比擬弱(優良的接口應當對輸出輸入能夠湧現的毛病信息停止捕獲,並供給清晰清楚明了的處置成果),很輕易湧現毛病,調試艱苦,現實運用中普通不建議應用這類方法,應用時迭代次數也不克不及跨越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;
}
此辦法重要應用於:應用場景一:關於對象或變量應用次數比擬少,應用一次今後就不會再應用的場景;應用場景二:關於內存資本比擬稀缺的及時性請求不是太高的嵌入式體系設計中多會采取此種方法;
法式完成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 >(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;
}
}
此辦法普通用於:對象或變量在法式運轉的全部性命周期都存在或頻仍挪用的場景,如挪用內部WebService接口、籠統連續化層、經常使用設置裝備擺設文件參數加載等等
測試用例:
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
關於算法設計,不要自覺遵守概念,概念是逝世的,人是活的(在這個須要crazy man的時期,有設法主意比循序漸進更有優勢),只用聯合詳細的運用場景能力設計出優良的算法和構造。
吐槽一下:小我以為優良的數據構造設計可以簡化算法設計的龐雜度進步代碼的可讀性、法式的擴大性及履行效力;
再吐槽一下:做需求剖析的時刻應當遵守三點准繩:1.從用戶角度及其思想方法剖析;2.用戶說的紛歧定是他們真正想要的;3.用戶說的紛歧定是對的。做法式開辟遵守准繩:積極晉升本身咀嚼,站在用戶應用角度和應用場景剖析功效;例如你做後台接口開辟,你的用戶就是接口挪用者,你應當斟酌接口功效是甚麼,應用者在甚麼情形下會挪用,傳入參數能夠招致哪些異常,你的接話柄現中能夠湧現哪些異常並對能夠湧現的異常停止捕捉,清晰清楚明了的輸入,優越的函數自閉性;假如你是弄前台,那你應當在包管營業完成的基本上從用戶應用習氣等方面把本身當作應用者來設計UI。很成心思對不,需求、開辟多了天然就明確了O(∩_∩)O~。