深度理解遞歸+遞歸經典問題實戰

內涵

深度理解遞歸+遞歸經典問題實戰

定義數組

在數學與計算機科學中,**遞歸(Recursion)是指在函數的定義中使用函數自身的方法。**實際上,遞歸,顧名思義,其包含了兩個意思: 和 ,這正是遞歸思想的精華所在bash

遞歸思想的內涵數據結構

深度理解遞歸+遞歸經典問題實戰

遞歸就是有去(遞去)有回(歸來)函數

  • **「有去」**是指:遞歸問題必須能夠分解爲若干個規模較小,與原問題形式相同的子問題,這些子問題能夠用相同的解題思路來解決,就像上面例子中的鑰匙能夠打開後面全部門上的鎖同樣
  • **「有回」**是指 : 這些問題的演化過程是一個從大到小,由近及遠的過程,而且會有一個明確的終點(臨界點),一旦到達了這個臨界點,就不用再往更小、更遠的地方走下去

遞歸的基本思想就是把規模大的問題轉化爲規模小的類似的子問題來解決oop

遞歸的三要素ui

  • 明確遞歸終止條件;
  • 給出遞歸終止時的處理辦法;
  • 提取重複的邏輯,縮小問題規模。

遞歸的應用場景spa

  1. 問題的定義是按遞歸定義的(Fibonacci函數,階乘,…);
  2. 問題的解法是遞歸的(有些問題只能使用遞歸方法來解決,例如,漢諾塔問題,…);
  3. 數據結構是遞歸的(鏈表、樹等的操做,包括樹的遍歷,樹的深度,…)。

經典遞歸問題實戰

階乘3d

public class Factorial {

	public static long f( int n )
	{
		if ( n == 1 ) /* 遞歸終止條件 */
			return(1); /* 簡單情景 */
		return(n * f( n - 1 ) ); /* 相同重複邏輯,縮小問題的規模 */
	}

	public static long f_loop( int n )
	{
		long result = n;
		while ( n > 1 )
		{
			n--;
			result = result * n;
		}
		return(result);
	}
}
複製代碼

斐波納契數列指針

public class FibonacciSequence {

	public static int fibonacci( int n )
	{
		if ( n == 1 || n == 2 ) /* 遞歸終止條件 */
		{
			return(1); /* 簡單情景 */
		}
		return(fibonacci( n - 1 ) + fibonacci( n - 2 ) ); /* 相同重複邏輯,縮小問題的規模 */
	}

	public static int optimizeFibonacci( int first, int second, int n )
	{
		if ( n > 0 )
		{
			if ( n == 1 ) /* 遞歸終止條件 */
			{
				return(first); /* 簡單情景 */
			}else if ( n == 2 ) /* 遞歸終止條件 */
			{
				return(second); /* 簡單情景 */
			}else if ( n == 3 ) /* 遞歸終止條件 */
			{
				return(first + second); /* 簡單情景 */
			}
			return(optimizeFibonacci( second, first + second, n - 1 ) ); /* 相同重複邏輯,縮小問題規模 */
		}
		return(-1);
	}

	public static int fibonacci_loop( int n )
	{
		if ( n == 1 || n == 2 )
		{
			return(1);
		}
		int	result	= -1;
		int	first	= 1; /* 本身維護的"棧",以便狀態回溯 */
		int	second	= 1; /* 本身維護的"棧",以便狀態回溯 */
		for ( int i = 3; i <= n; i++ ) /* 循環 */
		{
			result	= first + second;
			first	= second;
			second	= result;
		}
		return(result);
	}

	public static int fibonacci_array( int n )
	{
		if ( n > 0 )
		{
			int[] arr	= new int[n]; /* 使用臨時數組存儲斐波納契數列 */
			arr[0]		= arr[1] = 1;
			for ( int i = 2; i < n; i++ ) /* 爲臨時數組賦值 */
			{
				arr[i] = arr[i - 1] + arr[i - 2];
			}
			return(arr[n - 1]);
		}
		return(-1);
	}
}
複製代碼

楊輝三角的取值code

public static int getValue( int x, int y )
{
	if ( y <= x && y >= 0 )
	{
		if ( y == 0 || x == y ) /* 遞歸終止條件 */
		{
			return(1);
		}else{
			/* 遞歸調用,縮小問題的規模 */
			return(getValue( x - 1, y - 1 ) + getValue( x - 1, y ) );
		}
	}
	return(-1);
}
}
複製代碼

迴文字符串的判斷

/**
 * Title: 迴文字符串的判斷
 * Description: 迴文字符串就是正讀倒讀都同樣的字符串。如"98789", "abccba"都是迴文字符
 * 兩種解法:
 * 遞歸判斷;
 * 循環判斷;
 */
public class PalindromeString {
	/**
	 * @description 遞歸判斷一個字符串是不是迴文字符串
	 * @return
	 */
	public static boolean isPalindromeString_recursive( String s )
	{
		int	start	= 0;
		int	end	= s.length() - 1;
		if ( end > start ) {//遞歸終止條件:兩個指針相向移動,當start超過end時,完成判斷 
			if ( s.charAt( start ) != s.charAt( end ) ){
				return(false);
			}else{
				/* 遞歸調用,縮小問題的規模 */
				return(isPalindromeString_recursive( s.substring( start + 1 ).substring( 0, end - 1 ) ) );
			}
		}
		return(true);
	}

	/**
	 * @description 循環判斷迴文字符串
	 * @return
	 */
	public static boolean isPalindromeString_loop( String s )
	{
		char[] str = s.toCharArray();
		int	start	= 0;
		int	end	= str.length - 1;
		while ( end > start ) //循環終止條件:兩個指針相向移動,當start超過end時,完成判斷 
		{
			if ( str[end] != str[start] )
			{
				return(false);
			}else{
				end--;
				start++;
			}
		}
		return(true);
	}
}
複製代碼
相關文章
相關標籤/搜索