递归算法

笔记:数据结构与算法

隐身守侯 提交于 2019-12-03 02:31:02
数据结构与算法 常用排序算法 实现比较丑陋,勿喷啊 冒泡排序 :从前向后比较相邻的元素。如果前一个比后一个大,就交换他们两个,每一轮把一个最大的数运到数组最后面。 public static int[] sort(int[] arr) { int len = arr.length; // 冒泡总次数 for (int i = 1; i < len; i++) { boolean flag = true; // 每次冒泡过程 for (int j = 0; j < len - i; j++) { if (arr[j] > arr[j + 1]) { MyUtils.swap(arr, j, j + 1); flag = false; } } if (flag) { // 如果一个冒泡过程没改变,退出返回已经有序 break; } } return arr; } 选择排序 :每次从未排序数组中找一个最小的元素,放到以有序数组后面 public static int[] sort(int[] arr) { int len = arr.length; // 选择次数 for (int i = 0; i < len - 1; i++) { int min = i; // 每次选择过程 for (int j = i + 1; j < len; j++) { if (arr[j] < arr

JAVA数据结构和算法 6 递归

老子叫甜甜 提交于 2019-12-03 02:11:29
递归:直接或者间接地调用自己。比如计算连续数的阶乘,计算规律:n!=(n-1)!*n。 每个递归方法都有一个基值(终止)条件,以防止无线地递归下去,以及由此引发的程序崩溃。 采用递归是因为它可以从概念上简化问题,递归算法结构清晰、可读性强,且容易采用数学归纳法证明算法正确性。然而时间花费和空间花费都比非递归算法更大。 关于递归与分治: 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题与原问题相同且相互独立。 递归地解这些子问题 ,然后将各子问题的解合并得到原问题的解。 使用分治思想设计出的算法一般是递归算法, 所以分治问题的时间复杂度也可以用递归方程来分析 。 关于递归与回溯: 回溯也是一种算法思想,可以用递归实现。通俗点讲回溯就是一种试探,类似于穷举,但回溯有“剪枝”功能。 来源: https://www.cnblogs.com/lsh0908/p/11770783.html

eetCode刷题-递归篇

二次信任 提交于 2019-12-03 01:36:05
递归是算法学习中很基本也很常用的一种方法,但是对于初学者来说比较难以理解(PS:难点在于不断调用自身,产生多个返回值,理不清其返回值的具体顺序,以及最终的返回值到底是哪一个?)。因此,本文将选择LeetCode中一些比较经典的习题,通过简单测试实例,具体讲解递归的实现原理。本文要讲的内容包括以下几点: 理解递归的运行原理 求解递归算法的时间复杂度和空间复杂度 如何把递归用到解题中(寻找递推关系,或者递推公式) 记忆化操作 尾递归 剪枝操作 理解递归的运行原理 例1求解斐波那契数列 题目描述(题目序号:509,困难等级:简单): 求解代码(基础版): class Solution { public int fib(int N) { if(N <= 1) return N; return fib(N - 1) + fib(N - 2); } } 现在以N = 5为例,分析上述代码的运行原理,具体如下图: 递归的返回值很多,初学者很难理解最终的返回值是哪个,此时可以采用上图的方式画一个树形图,手动执行递归代码,树形图的叶节点即为递归的终止条件,树形图的根节点即为最终的返回值。树形图的所有节点个数即为递归程序得到最终返回值的总体运行次数,可以借此计算时间复杂度,这个问题会在后文讲解。 例2 二叉树的三种遍历方式 二叉树的遍历方式一般有四种:前序遍历、中序遍历、后序遍历和层次遍历

斐波那契数列(递归、非递归算法)

匿名 (未验证) 提交于 2019-12-03 00:39:02
题目 斐波那契数,亦称之为斐波那契数列(意大利语: Successione di Fibonacci),又称黄金分割数列、费波那西数列、费波拿契数、费氏数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……在数学上,斐波那契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*),用文字来说,就是斐波那契数列由 0 和 1 开始,之后的斐波那契数列系数就由之前的两数相加。 限制 时间限制:1秒 空间限制:32768K package com . algorithm ; import java . util . Scanner ; /** * 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39 * @日期:2018年6月30日 下午10:11:43 * @作者:Chendb */ public class Fibonacci { public static void main ( String [] args ) { Scanner scanner = new Scanner ( System . in ); int n = scanner . nextInt (); System . out . println ( fibonacciRecursion ( n )); System . out

递归算法和经典递归例子

匿名 (未验证) 提交于 2019-12-03 00:37:01
一、 什么叫递归 也就是自身调用自己。 二、 一般什么时候使用递归? 还有些 如二叉树, 结构本身固有递归特性 ;此外,有一类问题,其 本身没有明显的递归结构,但用递归程序求解比其他方法更容易 编写程序。 三、 经典递归算法 递归阶乘 n! = n * (n-1) * (n-2) * ...* 1(n>0) public static Integer recursionMulity(Integer n){ if(n==1){ return 1; } return n*recursionMulity(n-1); } 2、 汉诺塔问题 public static void hanio(int n,char a,char b,char c){ 8 if(n==1) 9 System.out.println("移动"+n+"号盘子从"+a+"到"+c); 10 else{ 11 hanio(n-1,a,c,b);//把上面n-1个盘子从a借助b搬到c 12 System.out.println("移动"+n+"号盘子从"+a+"到"+c);//紧接着直接把n搬动c 13 hanio(n-1,b,a,c);//再把b上的n-1个盘子借助a搬到c 14 } 15 } 3.判定一系列字符串中是否有相同的内容 public class Crf{ public static void main

背包问题的递归和非递归算法

匿名 (未验证) 提交于 2019-12-03 00:34:01
/** 简单背包问题 问题定义: 有一个背包重量是S,有n件物品,重量分别是W0,W1...Wn-1 问能否从这n件物品中选择若干件放入背包中使其重量之和正好为S */ #include <iostream> #include <algorithm> #include <vector> #include <string> using namespace std; const int maxsize=100; int n,S;//n是有多少中物品,S是要凑足的重量 bool visit[maxsize];//标记是否被访问过,别访问过标记为1,没有访问过为0 int w[maxsize];//记录每一种物品的重量 int q[maxsize];//相当于一个栈,存储被访问过的物品的编号 int beibao() { int top=-1,begin=0,sum=0; int i; while(top!=-2) { //从第一个物品开始循环 for(i=begin;i<n;i++) { //如果没有被访问过,并且加上重量之和小于S if(!visit[i] && w[i]+sum<=S) { sum+=w[i];//在sum上加上当前物品的重量 q[++top]=i;//把物品的编号存入q[]中 begin=0;//从头开始访问 visit[i]=1;//该结点访问过标记 if(sum

函数递归总结

匿名 (未验证) 提交于 2019-12-03 00:33:02
1 函数递归的定义:函数自己直接或者间接的调用自己的函数,直到满足一个条件结束自己调用自己的函数的过程。每次调用函数都会开辟新的空间,递归调用可以看做是函数的嵌套调用。 2 递归算法的设计基本思想:对于一个复杂的问题:把原问题分解成相对简单的若干子问题,继续下去,直到子问题简单到能够直接求解。也就是到了递归的结束条件,也叫递归出口。 3 关键处:递归出口,逐步向出口逼近。 4 递归缺点:运行效率低。不建议使用。 5 递归的实例: (1)斐波那契数列(黄金分割数列) 例如:1,1,2,3,5,8,13..........在数学上,斐波那契数列被递归这样定义:F(0)=0;F(1)=1;F(n)=F(n-1)+F(n-2),(n>=2); 现在用递归求第100个数。 代码如下: static int count(int n){ if(n==1||n==2) { return 1; } return count(n-1)+count(n-2); } public static void main(String args[]) { int sum=count(100); System.out.println(sum); } (2)求解阶乘。例如求解100的阶乘 代码如下: public class Digui { public static int digui(int n){ if(n=

day16 -- 递归函数,二分查找

匿名 (未验证) 提交于 2019-12-03 00:32:02
一,递归函数 1,1初始递归 递归的最大深度 : 998 递归函数如果不受外力的阻止会一直执行下去,但是函数的每次调用都会产生一个属于自己的名称空间,如果一直调用下去的话,会出现名称空间过多导致的内存问题,所以为了避免这种现象,强制将递归层数控制在了997 def foo(n): print (n) n = n + 1 foo(n) foo( 1 1,2 ,递归示例 问alex多大了,告诉你alex比egon大两岁, 然后去问egon多大了,egon说我比wusir大两岁, 然后又去问wusir,wusir说他比太白大两岁, 然后去问太白,太白说他18,这样就可以计算出alex到底多大了 age(4) = age(3) + 2 age( 3) = age(2) + 2 age( 2) = age(1) + 2 age( 1) = 18 然后我们用函数表示 def age(n): if n == 1 : return 18 else : return age(n - 1) + 2 print (age(4 )) # 24 解析: def age(4):   if n == 1:     return 26   else:     return age(3) + 2 def age(3):   if n == 1:     return 26   else:     return

全排列递归(解决了重复字符问题)

匿名 (未验证) 提交于 2019-12-03 00:30:01
网上有很多讲解全排列递归的算法思路以及程序,所以在此本菜鸟就不再写一遍了。 今天的重点在解决重复字符方面,感觉网上博客里的解决思路大都一致,写一个isSwap函数,然后在递归主体里判断一下函数返回true还是false,大神们也都po出了程序运行图。然而我这么写的程序最终跑不出来预期结果,因此我分析了一下,觉得可以有一个更为简单的办法去重。 要点就是:如果发现待交换的两个字符str[i] == str[k],并且i!=k时,就不交换了,如此即可去重 可运行代码如下(去重判断部分已加粗): if(i==k || (str[i]!=str[k])){ 运行结果: 文章来源: 全排列递归(解决了重复字符问题)

递归、迭代求斐波那契数列

匿名 (未验证) 提交于 2019-12-03 00:29:01
今天给大家分享一下基本算,就是使用递归、迭代求斐波那契数列,同时给解释迭代算法求解波那契数列的算法的时间复杂性和空间复杂性和分析递归算法求解波那契数列的算法的时间复杂性和空间复杂性。 对于迭代,确定迭代变量。在可以用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式或关系。迭代关系式的建立是解决迭代问题的关键,通常可以使用递推或倒推的方法来完成。而且要对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。下面就是迭代算法: #include<stdio.h> #define N 80 long fun( int);//函数调用 int main()//主函数 { int n;//定义 scanf("%d",&n);//输入 printf("the value is %ld\n",fun(n)); return 1; } long fun(int n) { long i; long Fib[N]; //定一个数组 Fib[0]=0;Fib[1]=1; //迭代算法控制 for(i=2;i<=n;i++) Fib[i]=Fib[i-1] + Fib[i-2]; return Fib[n]; } 结果: