1.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
题目分析:第7天卖完剩2只,则第六天卖完剩2*(2+1)只,第五天卖完剩2*(2*(2+1)+1)只...依次类推,用Fun(7)表示未卖之前的总数,相当于第0个村庄,那么Fun(6)表示路过第一个村庄,...依次类推,用F(0)表示路过第七个村庄,所以当m=0时,return 2,为该程序的出口。其他情况return 2*(Fun(n-1)+1);
算法结构:
递归体:return 2*(Fun(n-1)+1)
代码实现:
package test;
/*
* 一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。
* 这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?
* 经过每个村子卖出多少只鸭子?
*/
public class Test01 {
public static void main(String[] args) {
int sum = Duck(7);//调用方法
System.out.println("总共有" + Duck(7) + "只鸭子");
for (int i = 1; i <= 7; i++) {//利用for循环输出经过每个村子卖出鸭子的个数
System.out.println("第" + i + "个村子卖出" + (sum / 2 + 1) + "只鸭子");
sum = sum / 2 - 1;//剩余的鸭子数为前一天剩余的鸭子数的一半减1
}
}
/*
* Duck为递归方法,参数n代表经过的村子个数
*/
public static int Duck(int n) {
if (n == 0) {//0表示第七个村子
return 2;
} else {
return 2 * (Duck(n - 1) + 1);
}
}
}
2.角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。
如:输入22,
输出 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
STEP=16
题目分析:首先输入一个自然数n,调用函数gujiao(int n),将n的值传给形参。每次进行判断如果是偶数,则n=n/2,是奇数则 n=(n*3+1),递归调用gujiao(n)函数,直到n=1的时候,返回步数,调用结束。If(n==1){return step;}为出口,return gujiao(n)为函数体。
算法结构:
出口:If(n==1){return step;}
递归体:return gujiao(n)
代码实现:
package test;
import java.util.Scanner;
/*
* 角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,
* 则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。
* 求经过多少次可得到自然数1。
*/
public class Test02 {
public static void main(String[] args) {
System.out.println("请输入一个自然数:");
Scanner sc = new Scanner(System.in);
gujiao(sc.nextInt());
System.out.println("\n" + "step=" + step);
}
static int step = 0;//静态方法定义经过的次数
/*
* gujiao为递归方法,参数n代表自然数
*/
public static int gujiao(int n) {
System.out.print(n + " ");
step++;//没经过一次,次数加1
while (true) {
if (n == 1) {//递归出口
return step;
} else {
if (n % 2 == 0) {
n = n / 2;
} else {
n = n * 3 + 1;
}
}
return gujiao(n);//递归体
}
}
}
3.电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。
题目分析:
2对应的是abc 3对应的是def 4对应的是ghi 5对应的是jkl
6对应的是mno 7对应的是pqrs 8对应的是tuv 9对应的是wxyz。
2对应3种可能性 3对应3种可能性 4对应3种可能性 5对应3种可能性
6对应3种可能性 7对应4种可能性 8对应3种可能性9对应4种可能性。
利用数组将这些信息存储起来,在利用循环进行遍历。输入3到11位数字,输出组合情况,并且输出组合情况的总数
算法分析:
int类型存放不下11位的数字,这里用String类型接收。根据题目要求,定义数组,用来存放字母。为了方便输出组合,把输入的数字转换为字符后,用数组来存放,再用回溯法实现组合输出.
代码实现:
package test;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* 题目描述:
* 电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。
* 那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。
* 现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。
*/
public class Test06 {
static String[] str= new String[] {"0","1","abc","def",
"ghi","jkl","mno","pqrs","tuv","wxyz"};//定义每个数字对应的字符
public static void main(String[] args) {
int sum=1;//定义变量统计组合数
System.out.println("请输入3到11位的电话号码:");
Scanner sc=new Scanner(System.in);
String s=sc.next().toString();//将输入的数字转换为字符
String[] s1 = s.split("");//将输入的一串数字分离,并赋给数组s1保存
int len = s1.length;//输入数字长度
for(int i=0;i<len;i++){ //统计组合数
sum *= str[Integer.valueOf(s1[i])].length();
}
System.out.println("组合数sum = "+sum);
System.out.println("可能的组合为:");
List<String> x = letterCombinations(s);
System.out.println(x.toString());
}
static StringBuffer sb = new StringBuffer();
public static List<String> letterCombinations(String digits) {
if (digits.length() == 0) {
return null;
}
List<String> answer = new ArrayList<String>();
zuhe(digits , 0 , answer);//开始回溯
return answer;
}
/*
* zuhe方法用于实现字母的每种可能的组合
*/
private static void zuhe(String digits , int n, List<String> answer) {
if (n == digits.length()) {
answer.add(sb.toString());
return;
}
for (int i = 0; i < str[digits.charAt(n)-'0'].length(); i++) {
sb.append(str[digits.charAt(n)-'0'].charAt(i));
zuhe(digits, n + 1, answer);
sb.deleteCharAt(sb.length() - 1);
}
}
}
4.日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。分完 后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?
题目分析:从数学的思维来分析,倒推:
总共2520,分到最后每人是2520/6=420 ;
老六拿到后连同原先的桔子分1/3给老大,所以老六没分给老大之前是420*3/2=630,分给老大的是630/3=210;
老大最后也是420,所以老大在分给老二后的橘子数为420-210=210;而老大将分给你的桔子的1/8给老二,故老大未分给老二前的橘子数为210*8/7=240; 老二拿到后连同原先的桔子分1/7给老三,设老二本身的橘子树为x,则(x+30)*6/7=420;老二本身的橘子数为460;
….
以此类推
代码实现:
package test;
/**
* 日本著名数学游戏专家中村义作教授提出这样一个问题:
* 父亲将2520个桔子分给六个儿子。分完 后父亲说:
* “老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;
* 老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;
* 老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。
* 结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?
*/
public class Test04 {
public static void main(String[] args) {
digui();//调用方法
}
/*
* 构造方法
*/
public static void digui(){
int left = 0;//前一个给下一个的桔子数
int avge=2520/6;//最终每个人手里的桔子个数
int[] a=new int[6];//定义数组,分别代表每个儿子原来的桔子个数
for (int i = 0; i < 6; i++)
{
if (0 == i)//求老大桔子数时,利用老六与老大桔子数量的关系求解
{
a[i] = (avge - 210)*(8 - i)/(7 - i) - left;
left = a[i] + left - (avge - 210);
}
else
{
a[i] = avge*(8 - i) / (7 - i) - left;
left = a[i] + left -avge;
}
}
for(int j=0;j<6;j++){//遍历输出每个儿子原来的桔子个数
System.out.print(a[j]+" ");
}
}
}