蓝桥杯常用算法知识点:1.递归与循环

递归的好处:简单了程序员


要点:发现相似性,设置出口 (构造相似性,添参数)


元素:调用自身(参数变化)






递归思想:
我做最后一个/我做第一个,你告诉我谁是最后一个(加参)
然后其他的交给长得跟我一样的下属。(相似性)
并且要求你到什么时候就不能往下交了(设置出口)


递归类型:有返回&没返回
没返回:老板做(1【需要加参】或尾),然后推给下属,并限定到哪
有返回:老板最后返回总的情况,推给下属,限定到哪,底层下属返回一个


public class Main {
public static void main(String[] args) {
f(9);	//最简单的递归:老板给数据		这到墙的距离
f2(0,9);   //任性的组长:我就要做最简单的		墙到那的距离
}


public static void f(int n){  //下属的想法和我一样
	if(n>0){f(n-1);}      //我打印输入位10,前面交给下级打印,打印到0就可以
	System.out.println(n);    //履行我打印输入位的诺言
	//推到0时(起始项):我最底层,只好乖乖干活了
}


public static void f2(int begin,int end){  //一旦发现递归无法表达,很可能是参数出现问题
	/**
	 * 设置出口
	 */
	if(begin>end){return;} //设置出口方式2:在全部程序这儿把关  
	System.out.println(begin);
	f2(begin+1,end);   //相识性:交给下属
	//设置出口方式1:在交给下属这儿把关。
}
}


=============================================================
求和示例:
public class Main {
/**
 * 踢皮球之递归求和
 * @param args
 */
public static void main(String[] args) {
	int a[]={2,5,3,9,12,7};
	int sum=f(a,0);
	System.out.println(sum);
}
//传数组有所问题,参数不能改变,无限循环
public static int f(int[] a,int begin){  //加上begin变化


	if(begin==a.length){return 0;}//最底层做了
	/**
	 * 主体部分
	 */
	int x=f(a,begin+1);  //传数组和起始变化
	return x+a[begin];  //返回数组总和:下属做的和我做的第一项
}
}


===============================================================
对比示例:
public class Main {
public static boolean f(String s1,String s2){
	if(s1.length()!=s2.length()){return false;}//第一轮筛选,长度筛选
	if(s1.length()==0){return true;}   //设置出口方式
	
	if(s1.charAt(0)!=s2.charAt(0)){return false;}//传入内容筛选:【new】指定字符内容是否相等
	return f(s1.substring(1),s2.substring(1));   //交给下级:【new】截取一段字符串
}	
	
public static void main(String[] args) {
	System.out.println(f("abc","abcd"));
	System.out.println(f("abc","abc"));
}
}


===============================================================
手动加相似:
public class Main {
//在n个球中,取m个不放回,有多少种不同的取法
public static int f(int n,int m){
	/**
	 *出口情况讨论 
	 */
	if(n<m){return 0;}    //底层有结果多种情况,写得有问题,初处理为0
	if(n==m){return 1;}   //当相同,初处理为1
	if(m==0){return 1;}   //底层初处理为0时,有一种情况
	
	
	/**		平地起风雷【记忆】
	 * 假设两种情况分为两堆(划分标准):一堆假设有一个红球,一堆没有
	 * 所以堆1是n-1中取m-1,堆2是n-1中取m个
	 * 两堆相加就是总取法
	 */	
	return f(n-1,m-1)+f(n-1,m);   //交给下级的操作(无中生有情况)
}
	
public static void main(String[] args) {
int k=f(10,3);   //10个取3个有几种方法
System.out.println(k);
}
}


================================================================
打印所有的排列:
//求n个元素的全排列
//abc acb bac bca cab cba
public class Main {
public static void f(char data[],int k){   //仅传数组肯定不够的,k:当前焦距元素
	/**
	 * 当k移到length时,就可以输出了
	 */
	if(k==data.length){   //打印排列
		for(int i=0;i<data.length;i++){
			System.out.print(data[i]+" ");
		}
		System.out.println();
	}
	/**
	 * 方式理解:
	 * 1.每个数和第一个数交换,交换到最后一个数
	 * 2.中止,下一个数和第一个数交换,交换到最后一个
	 * 3.一直到最后一个数为首数,打印交换后的情况,然后回溯数组		执行完程序,返回上一层
	 * 4.倒数第二个数打印交换后的情况,回溯数组。。。一直到第一个数
	 */
	for(int i=k;i<data.length;i++){   //让每个元素与第一个元素交换:出口已经包含在k中,k有尽头
		{char temp=data[k];
		data[k]=data[i];
		data[i]=temp;}  //试探!!!


		f(data,k+1);  //交给下级解决:下一个数也是
		
	/*	{char temp=data[k];
		data[k]=data[i];
		data[i]=temp;}  //回溯:避免混乱!!!此处不需要回溯!!!	*/	
	}	
}
	
		
public static void main(String[] args) {
	char data[]="ABC".toCharArray();   //"字符串".toCharArray();   可以将字符串分开存入数组中
			f(data,0);  //调用这个方法就可以全排列,0:表示从0开始焦距
}
	}


============================================================
两个串最长公共子序列的长度:
public class Main {
//求两个串最长公共子序列的长度
//abcdef    abc  abd  bdf


public static int f(String s1,String s2){
	if(s1.length()==0||s2.length()==0){
	return 0;	
	}
		/**
		 * 主体部分
		 */
	if(s1.charAt(0)==s2.charAt(0)){     //如果头相同
		return f(s1.substring(1),s2.substring(1))+1;    //在交给下级的比较结果中加1 
	}else{
		return Math.max(f(s1.substring(1),s2),f(s1,s2.substring(1)));	//返回:max的选择执行,谁大执行谁
		//执行方式(降低规模!!!):谁大切谁,轮流切
	}
}	
/**
 * 主体逻辑:
 * 1.比较第一个,相同就加1继续执行(过程)
 * 2.不同就去掉长的头元素,继续比较(变化)
 * 3.一直到有一方为0,返回0种情况(出口)
 * @param args
 */
public static void main(String[] args) {
int k=f("fabcdk","xbacd");
System.out.println(k);			
}
	}


===============================================================
反转串:
public class Main {
/**
 * 反转串
 * 把cfk变成kfc
 * @param args
 */
public static String f(String s){   //把字符传到方法中
	if(s.length()<=1){return s;}
	return f(s.substring(1))+s.charAt(0);    //我把第1个拿出来,下属处理好之后我放在最后
}
	/**
	 * 步骤:
	 * 1.我先把第一个数拿下来
	 * 2.然后交给下属,下属把第一个数拿下来。。。
	 * 3.一直到最底层,只有一个数,拿了又放回去
	 * 4.上一级把东西放后面,上一级再放后面
	 * 5.到最后我把东西放最后面
	 * @param args
	 */
public static void main(String[] args) {
System.out.println(f("cfk"));
}
	}


================================================================
打印杨辉三角形的某一层:
public class Main {
/**
 * 打印杨辉三角形的某一层
 * @param args
 */
	public static int f(int m,int n){  //指定数字的打印
		//边缘处理
		if(m==1||n==1){return 1;}   //推到底层,m,n为1时值为1
		if(m==n){return 1;}      //m与n相等时值为1
		
		//主体部分
		return f(m-1,n)+f(m-1,n-1);   //上面的那个数和左上角之和
	}
	
	public static void main(String[] args) {
int level=5;   //打印第几层
for(int i=1;i<=level;i++){   
	System.out.print(f(level,i)+" ");
}	
}
	}


================================================================
m个A和n个B排列:
public class Main {
/**
 *m个A和n个B排列
 * @param args
 */


public static int g(int m,int n){
	if(m==0||n==0){return 1;}  //出口


	return g(m-1,n)+g(m,n-1);   //分成两部分相加
}




public static void main(String[] args) {
	System.out.println(g(3,2));   //传数值
}
}


=================================================================
对n加法划分:
public class Main {
/**对n加法划分(记忆)
 * 6
 * 5+1
 * 4+2,4+1+1
 * 3+3,3+2+1,3+1+1+1
 * 2+2+2,2+2+1+1,2+1+1+1+1
 * 1+1+1+1+1+1+1
 * 打印出来。
 * @param args
 */
public static void f(int n,int a[],int k){
	if(n<=0){    //打印机构
		for(int i=0;i<k;i++){
			System.out.print(a[i]+" ");
		}
		System.out.println();
		return;
	}
	for(int i=n;i>0;i--){
			if(k>0&&i>a[k-1]){continue;}   //排除那些不是???	
	/**
	 * 将最大的那个数6记录给k=0,然后打印出1位
	 * 下一位5记录给k=0,然后1记录给k=1,输出
	 * 下一位4,记录给k=0,将2抛给下一级
	 * 		然后2记录给k=1,将数组输出
	 * 		下一级还没结束,将1记录给k=1,将1抛给下一级
	 * 			下一级将1记录给k=2,打印出 4 1 1
	 * 
	 * 算法特点:(细胞分裂)将一个数分割传代,分割部分再像前一个数一样,不断分裂
	 */
	a[k]=i;    //记录主数
	f(n-i,a,k+1);   //减去的数继续进行划分:子数据重新执行此方法,划分后再划分
	}
}
		
public static void main(String[] args) {
int a[]=new int[100];   //缓存
	f(6,a,0);//传数值,数组,指标
}
}


=============================================================
最后一道递归看不懂题意,以后补上





















  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值