【转】递归算法的解题思路二
转自 http://blog.csdn.net/yzx226/article/details/6195999
递归算法的解题思路:
首先步骤分解,写出最后一次递归(n=1)的计算公式,然后是倒数第二次(n=2),n=3....,最后归纳出递归算法
如第二题:fn(1)=1;f(2)=1;f(3)=f(1)+f(2);----> f(n)=f(n-2)+f(1),那么很容易就写出这个递归函数
f(n)={n<=2?1:fn(n-2)+f(n-1)}
1、编写一个方法用于验证指定的字符串是否为反转字符,返回true和false。请用递归算法实现。(反转字符串样式为"abcdedcba")
2、一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30个是多少
3、一列数的规则如下: 1、12、123、1234、12345、123456......,求第n个数的递归算法(n<=9)。
4、将一整数逆序,如987654321变为123456789。
5、一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能行有多少种?
以上的前提:不能用数组 或转成字符串处理,也不能用内置函数,如C#的幂函数(Math.Pow)
- namespace RecursionAlgorithms
- {
- class Program
- {
- private static bool fn1(ref string str, ref int from, ref int to)
- {
- if (from >= to) return true;
- if (str[from++] != str[to--]) return false;
- return fn1(ref str, ref from, ref to);
- }
- private static int fn2(int i)
- {
- return i <= 2 ? 1 : fn2(i - 2) + fn2(i - 1);
- }
- private static long fn3(long x, ref long n)
- {
- return (x <= 1) ? x : fn3(x - 1, ref n) + x * (n *= 10);
- }
- private static long fn4(long x, ref long n)
- {
- return (x < 10) ? x : fn4(x / 10, ref n) + (x % 10) * (n *= 10);
- }
- private static long fn5(int n, int sum)
- {
- if ((n == 1 && sum <= 10) || (sum == n * 10)) return 1;
- if (sum > n * 10 || sum < 0) return 0;
- long ok = 0;
- for (int i = 0; i <= 10; i++)
- {
- ok += fn5(n - 1, sum - i);
- }
- return ok;
- }
- static void Main(string[] args)
- {
- string[] strs = { "", "a", "aa", "aba", "abba", "abcba", "ab", "abc", "abca" };
- for (int i = 0; i < strs.Length; i++)
- {
- string str = strs[i];
- int from = 0, to = str.Length - 1;
- Console.WriteLine("{0} is {1}", str, fn1(ref str, ref from, ref to));
- }
- for (int i = 1; i <= 30; i++) Console.Write("{0}:{1} /t", i, fn2(i));
- long n = 1, m = 1, t = 0;
- for (int i = 0; i <= 9; i++, n = m = 1)
- {
- Console.Write("/n {0} ==> {1}", t = fn3(i, ref n), fn4(t, ref m));
- }
- Console.WriteLine("/n{0}种可能性", fn5(10, 90));
- }
- }
- }
递归算法设计的基本思想是:对于一个复杂的问题,把原问题分解为若干个相对简单类同的
子问题,继续下去直到子问题简单到能够直接求解,也就是说到了递推的出口,这样原问题就有递推
得解。
关键要抓住的是:
(1)递归出口
(2)地推逐步向出口逼近
三、具体说明
1.汉诺塔
这是递归的超经典的例子,几乎每本程序设计书上谈到递归都会介绍。具体情景不再赘述。以我
上述的方法观之:(1)递归的出口在于disk数为一的时候
(2)向出口逼近:如果不是一,是n ,则我们先挪动上面n-1块disk,等上面挪完,即递归返回
的时候,我们挪动最底下的disk.
仅仅如此,一个貌似十分复杂的问题就解决了,因为挪动那n-1块disk的时候,会继续向上减少,
直到disk的数量为一为止。下面给出java程序编码(已测试过,运行正常):
import javax.swing.JOptionPane;
public class Hanoi {
private static final String DISK_B = "diskB";
private static final String DISK_C = "diskC";
private static final String DISK_A = "diskA";
static String from=DISK_A;
static String to=DISK_C;
static String mid=DISK_B;
public static void main(String[] args) {
String input=JOptionPane.showInputDialog("please input the number of the disks you
want me move.");
int num=Integer.parseInt(input);
move(num,from,mid,to);
}
private static void move(int num, String from2, String mid2, String to2) {
if(num==1){
System.out.println("move disk 1 from "+from2+" to "+to2);
}
else {
move(num-1,from2,to2,mid2);
System.out.println("move disk "+num+" from "+from2+" to "+to2);
move(num-1,mid2,from2,to2);
}
}
}
2.这是一个排列的例子,它所做的工作是将输入的一个字符串中的所有元素进行排序并输出,例
如:你给出的参数是"abc" 则程序会输出:
abc
acb
bac
bca
cab
cba
(1)算法的出口在于:low = high 也就是现在给出的排列元素只有一个时。
(2)算法的逼近过程:先确定排列的第一位元素,也就是循环中i所代表的元素,
然后 low+1 开始减少排列元素,如此下去,直到 low = high
public static void permute(String str) { char[] strArray = str.toCharArray(); permute(strArray, 0, strArray.length - 1); } public static void permute(char[] list, int low, int high) { int i; if (low == high) { String cout = ""; for (i = 0; i <= high; i++) cout += list[i]; System.out.println(cout); } else { for (i = low; i <= high; i++) { char temp = list[low]; list[low] = list[i]; list[i] = temp; permute(list, low + 1, high); temp = list[low]; list[low] = list[i]; list[i] = temp; } } }
3。这是一个组合的例子,与上述的例子相似,只是它所做的工作是,输出所给字符串中制定数
目的元素的组合种类
(1)程序出口在于n=1,此时只要输出目标数组的所有元素即可
(2)逼近过程,当n>1 的时候,我们先取第一个元素放入目标数组中,然后n-1,如此
下去,最后出来。
import javax.swing.JOptionPane; public class Combination { public static void main(String[] args) { String input = JOptionPane .showInputDialog("please input your String: "); String numString = JOptionPane .showInputDialog("please input the number of your Combination: "); int num = Integer.parseInt(numString); Combine(input, num); } private static void Combine(String input, int num) { char[] a = input.toCharArray(); String b = ""; Combine(a, num, b, 0, a.length); } private static void Combine(char[] a, int num, String b, int low, int high) { if (num == 0) { System.out.println(b); } else { for (int i = low; i < a.length; i++) { b += a[i]; Combine(a, num - 1, b, i + 1, a.length); b = b.substring(0, b.length() - 1); } } } }
浙公网安备 33010602011771号