遞歸陷阱——有27個人要喝水,每三個空瓶子可以換一瓶水,問需要買多少瓶水



有27個人要喝水,每三個空瓶子可以換一瓶水,問需要買多少瓶水?


完成這道題目時使用了遞歸,發現怎麼也不對,後面找到錯誤,記錄下來。


錯誤版本

public class buyWater {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for (int i = 5; i < 27; i++) {
			int out = count(i, i);
			System.out.println("買 " + i + " 瓶,可以得到 " + out + " 瓶");
			if (out >= 27) {
				System.out.println("需要買水:" + i + " 瓶");
				return;
			}
		}
	}

	public static int count(int num, int out) {
		int a = num / 3;
		out += a;
		int b = num - 3 * a;
		while((a+b)>=3) out = count(a+b,out);
		return out;

	}
}
執行結果:
<span style="white-space:pre">	</span>沒有打印輸出,調試發現,程序一直在while循環中,out不斷增加。
分析:
<span style="white-space:pre">	</span>當i=5,執行count,a=1,b=2,滿足while循環,調用count()。執行下一級count(),a=1,b=0,不滿足while條件,return。回到上一級count,a=1,b=2,a、b值沒變,
這就是問題所在了。所以,一直在while循環。
本質在於形參和實參。進入count後,看似仍然使用的a和b,實際上不同的變量,生命週期到本級count執行完(即return)就結束,也不會影響外一級的參數值,所以永遠滿足while循環。


解決方案:

<span style="font-size:12px;">//		while((a+b)>=3) out = count(a+b,out);
		if(a+b>=3) out=count(a+b, out);</span>
使用if判斷,下一屆count返回時,儘管a、b值沒變,但是if語句不會回去再執行一次。

注意:必須使用

<span style="font-size:12px;"><span style="white-space:pre">		</span>out = count(a+b,out);</span>
<span style="font-size:12px;"><span style="white-space:pre">	</span>不然只</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">count(a+b,out);仍然出現out就等於這一級count執行的結果,因爲下一級的out只是個形參,不會改變out的值。</span>


發佈了32 篇原創文章 · 獲贊 22 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章