蓝桥杯常用算法知识点:1.递归与循环
2016-03-09 17:15
239 查看
递归的好处:简单了程序员
要点:发现相似性,设置出口 (构造相似性,添参数)
元素:调用自身(参数变化)
递归思想:
我做最后一个/我做第一个,你告诉我谁是最后一个(加参)
然后其他的交给长得跟我一样的下属。(相似性)
并且要求你到什么时候就不能往下交了(设置出口)
递归类型:有返回&没返回
没返回:老板做(1【需要加参】或尾),然后推给下属,并限定到哪
有返回:老板最后返回总的情况,推给下属,限定到哪,底层下属返回一个
=============================================================
求和示例:
===============================================================
对比示例:
===============================================================
手动加相似:
================================================================
打印所有的排列:
============================================================
两个串最长公共子序列的长度:
===============================================================
反转串:
================================================================
打印杨辉三角形的某一层:
================================================================
m个A和n个B排列:
=================================================================
对n加法划分:
=============================================================
最后一道递归看不懂题意,以后补上
要点:发现相似性,设置出口 (构造相似性,添参数)
元素:调用自身(参数变化)
递归思想:
我做最后一个/我做第一个,你告诉我谁是最后一个(加参)
然后其他的交给长得跟我一样的下属。(相似性)
并且要求你到什么时候就不能往下交了(设置出口)
递归类型:有返回&没返回
没返回:老板做(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);//传数值,数组,指标 } }
=============================================================
最后一道递归看不懂题意,以后补上
相关文章推荐
- 4.1 Javascript:决策-switch/case语句
- 【转】XCode、Cocoa、Objective-C 的关系区别
- 删除
- 【Xamarin挖墙脚系列:关闭 OS X El Capitan 中 SIP 安全设置功能】
- CocoaLumberjack 学习总结(五)
- Activiti工作总结(二)
- 移动用户体验设计:iOS APP体验设计
- Spring实战 第一章 1.4 Spring 中的新内容
- Android中Volley的Request的自定义
- 【poj2125】Destroying The Graph 二分图最小点权覆盖集
- jedis调用redis之分页
- 进程控制开发
- JSON 之FastJson解析
- java中float和double的区别
- 编程之美---代理模式
- 为什么要在linux命令前加上 ./ ?
- Hash 表算法解析
- linux shell 管道命令(pipe)使用及与shell重定向区别
- 防止mysql注入
- swift表情emoji的转换