递归

【算法导论】贪心算法,递归算法,动态规划算法总结

主宰稳场 提交于 2020-02-23 10:26:55
一般实际生活中我们遇到的算法分为四类: 一>判定性问题 二>最优化问题 三>构造性问题 四>计算性问题 而今天所要总结的算法就是着重解决 最优化问题 《算法之道》对三种算法进行了归纳总结,如下表所示: 标准分治 动态规划 贪心算法 适用类型 通用问题 优化问题 优化问题 子问题结构 每个子问题不同 很多子问题重复(不独立) 只有一个子问题 最优子结构 不需要 必须满足 必须满足 子问题数 全部子问题都要解决 全部子问题都要解决 只要解决一个子问题 子问题在最优解里 全部 部分 部分 选择与求解次序 先选择后解决子问题 先解决子问题后选择 先选择后解决子问题 分治算法特征: 1)规模如果很小,则很容易解决。//一般问题都能满足 2)大问题可以分为若干规模小的相同问题。//前提 3)利用子问题的解,可以合并成该问题的解。//关键 4)分解出的各个子问题相互独立,子问题不再包含公共子问题。 //效率高低 【一】动态规划: 依赖:依赖于有待做出的最优选择 实质:就是分治思想和解决冗余。 自底向上(每一步,根据策略得到一个更小规模的问题。最后解决最小规模的问题。得到整个问题最优解) 特征:动态规划任何一个i+1阶段都仅仅依赖 i 阶段做出的选择。而与i之前的选择无关。但是动态规划不仅求出了当前状态最优值,而且同时求出了到中间状态的最优值。 缺点:空间需求大。 【二】贪心算法: 依赖

【算法导论】贪心算法,递归算法,动态规划算法总结

痴心易碎 提交于 2020-02-23 10:24:55
一般实际生活中我们遇到的算法分为四类: 一>判定性问题 二>最优化问题 三>构造性问题 四>计算性问题 而今天所要总结的算法就是着重解决 最优化问题 《算法之道》对三种算法进行了归纳总结,如下表所示: 标准分治 动态规划 贪心算法 适用类型 通用问题 优化问题 优化问题 子问题结构 每个子问题不同 很多子问题重复(不独立) 只有一个子问题 最优子结构 不需要 必须满足 必须满足 子问题数 全部子问题都要解决 全部子问题都要解决 只要解决一个子问题 子问题在最优解里 全部 部分 部分 选择与求解次序 先选择后解决子问题 先解决子问题后选择 先选择后解决子问题 分治算法特征: 1)规模如果很小,则很容易解决。//一般问题都能满足 2)大问题可以分为若干规模小的相同问题。//前提 3)利用子问题的解,可以合并成该问题的解。//关键 4)分解出的各个子问题相互独立,子问题不再包含公共子问题。 //效率高低 【一】动态规划: 依赖:依赖于有待做出的最优选择 实质:就是分治思想和解决冗余。 自底向上(每一步,根据策略得到一个更小规模的问题。最后解决最小规模的问题。得到整个问题最优解) 特征:动态规划任何一个i+1阶段都仅仅依赖 i 阶段做出的选择。而与i之前的选择无关。但是动态规划不仅求出了当前状态最优值,而且同时求出了到中间状态的最优值。 缺点:空间需求大。 【二】贪心算法: 依赖

程序员面试金典.面试题 08.06. 汉诺塔问题

筅森魡賤 提交于 2020-02-23 03:42:52
1.题目描述 在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制: (1) 每次只能移动一个盘子; (2) 盘子只能从柱子顶端滑出移到下一根柱子; (3) 盘子只能叠在比它大的盘子上。 请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。 你需要原地修改栈。 示例1: 输入:A = [2, 1, 0], B = [], C = [] 输出:C = [2, 1, 0] 示例2: 输入:A = [1, 0], B = [], C = [] 输出:C = [1, 0] 提示: A中盘子的数目不大于14个。 2.解题思路 解题思路:递归与分治 这是一道递归方法的经典题目,乍一想还挺难理清头绪的,我们不妨先从简单的入手。 假设 n = 1,只有一个盘子,很简单,直接把它从 A 中拿出来,移到 C 上; 如果 n = 2 呢?这时候我们就要借助 B 了,因为小盘子必须时刻都在大盘子上面,共需要 4 步。 如果 n > 2 呢?思路和上面是一样的,我们把 n 个盘子也看成两个部分,一部分有 1 个盘子,另一部分有 n - 1 个盘子。 观察上图,你可能会问:“那 n - 1 个盘子是怎么从 A 移到 C 的呢?” 注意

迭代器,三元表达式,列表推存式,字典生成式,生成器生成式,生成器,递归

随声附和 提交于 2020-02-23 01:46:11
1. 迭代器 迭代器:他不是函数,只是一个称呼。 python中一切皆是对象(数据类型) 可迭代对象:含有 .__ iter __方法的数据类型就叫做可迭代对象。 除了数字类型,所有数据类型都是可迭代对象。可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象。 特点: 内置有 __iter__ 方法的都叫可迭代的对象。 x = 10 #则不是可迭代对象 可迭代对象位 .__iter__ s = "adc" s.__iter__() lt = [1,2,3] lt.__iter__() tup = (1,) tup.__iter__() se = {1} se.__iter__() dic ={"a":1} dic.__iter__() fw = open("text","a+",encoding="utf-8") fw.seek(0,0) fw.__iter__() # 除了数字类型,所有数据类型都是可迭代对象 迭代器对象 迭代器对象:含有 .__ iter __ 和 .__ next __方法的对象就是迭代器对象。 概念:可迭代的对象执行 __iter__ 方法得到的返回值。并且可迭代对象会有一个 __next__ 方法。 只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的

二分查找算法的递归与非递归实现(C++)

*爱你&永不变心* 提交于 2020-02-22 21:17:48
二分查找 又称 折半查找 , 首先, 假设表中元素是按升序排列, 将 表 中间位置 的关键字与查找关键字比较: 如果两者相等, 则查找成功; 否则利用中间位置将表分成前、 后两个子表: 如果中间位置的关键字大于查找关键字, 则进一步查找前一子表 否则进一步查找后一子表 重复以上过程, 直到找到满足条件的记录, 使查找成功, 或直到子表不存 在为止, 此时查找不成功。 二分查找算法的递归实现 //如果找到target,返回其所在数组下标,如果未找到,返回-1; int binary_search ( std :: vector < int > & sort_array , int begin , int end , int target ) { if ( begin > end ) { return - 1 ; } int mid = ( begin + end ) / 2 ; if ( target == sort_array [ mid ] ) { return mid ; } else if ( target < sort_array [ mid ] ) { return binary_search ( sort_array , begin , mid - 1 , target ) ; } else if ( target > sort_array [ mid ] ) {

第五周 程序和代码复用

£可爱£侵袭症+ 提交于 2020-02-22 19:10:16
函数是一段代码的表示,是一段具有特定功能的、可重用的语句组,是一种功能的抽象,一般函数表达特定功能,函数有两个作用,降低编程难度和代码复用。函数可以有参数,也可以没有,但必须保留括号。 def < 函数名 > ( < 参数 ( 0 个或多个 ) > ) : < 函数体 > return < 返回值 > y=f(x) 函数定义时,所指定的参数x是一种占位符。函数定义后,如果不经过调用,不会被执行。函数定义时,参数是输入、函数体是处理、结果是输出(IPO) 调用是运行函数代码的方式,调用时要给出实际参数,实际参数替换定义中的参数,函数调用后得到返回值。 可选参数传递函数定义时可以为某些参数指定默认值,构成可选参数。非可选参数是必选参数,可选参数可有可没有,必须放在必选参数的后面。 def < 函数名 > ( < 非可选参数 > , < 可选参数 > ) : < 函数体 > return < 返回值 > 可变参数传递:函数定义时可以设计可变数量参数,既不确定参数总数量。 def < 函数名 > ( < 参数 > , * b ) : < 函数体 > return < 返回值 > 参数传递的两种方式:函数调用时,参数可以按照位置或名称方式传递。 函数的返回值:函数可以返回零或多个结果。return用来传递返回值,函数可以有返回值也可以没有,可以有return,也可以没有。可以传递0个返回值

转:一文学会递归解题

独自空忆成欢 提交于 2020-02-22 15:53:40
前言 递归是算法中一种非常重要的思想,应用也很广,小到阶乘,再在工作中用到的比如统计文件夹大小,大到 Google 的 PageRank 算法都能看到,也是面试官很喜欢的考点 最近看了不少递归的文章,收获不小,不过我发现大部分网上的讲递归的文章都不太全面,主要的问题在于解题后大部分都没有给出相应的时间/空间复杂度,而时间/空间复杂度是算法的重要考量!递归算法的时间复杂度普遍比较难(需要用到归纳法等),换句话说,如果能解决递归的算法复杂度,其他算法题题的时间复杂度也基本不在话下。另外,递归算法的时间复杂度不少是不能接受的,如果发现算出的时间复杂度过大,则需要转换思路,看下是否有更好的解法 ,这才是根本目的,不要为了递归而递归! 本文试图从以下几个方面来讲解递归 什么是递归? 递归算法通用解决思路 实战演练(从初级到高阶) 力争让大家对递归的认知能上一个新台阶,特别会对递归的精华:时间复杂度作详细剖析,会给大家总结一套很通用的求解递归时间复杂度的套路,相信你看完肯定会有收获 什么是递归 简单地说,就是如果在函数中存在着调用函数本身的情况,这种现象就叫递归。 以阶乘函数为例,如下, 在 factorial 函数中存在着 factorial(n - 1) 的调用,所以此函数是递归函数 public int factorial ( int n ) { if ( n < = 1 ) {

递归、DFS感觉好难理解啊

扶醉桌前 提交于 2020-02-22 12:46:04
都说递归是一种易于理解的编码方式,但是感觉并没有那么轻松。 今天刷leetCode遇到一个分割回文串的问题,如下: 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ] 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/palindrome-partitioning 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 其中就有运用DFS和回溯的解法 完整代码如下 package com.LeeCode;import java.util.ArrayList;import java.util.List;public class VariesPalindrome { List<List<String>>list=new ArrayList<List<String>>(); String s; public List<List<String>> partition(String s) { //从头到尾递归+回溯。 this.s=s; //这个是满足的每一个集合 List<String>ll=new ArrayList<String>(); dfs(ll,0); return

递归调用转为循环

天大地大妈咪最大 提交于 2020-02-22 05:35:21
背景 有一个接口会返回json格式的字符串,json格式是嵌套的,类似这样的如下的结构,需要转换为一个list,当然最简单的写一个递归就可以了,但是有一句话: “所有的递归都可以转化为循环”,那么就练练自己的代码能力,温故而知新,用循环实现吧。 { "respData" : [ { "id" : 1 , "isvalid" : 1 , "orgName" : "汽车" , "parentId" : 0 , "subOrgList" : [ { "id" : 33 , "isvalid" : 1 , "orgName" : "客车" , "parentId" : 1 , "subOrgList" : [ { "id" : 37 , "isvalid" : 1 , "orgName" : "大客车" , "parentId" : 33 } , { "id" : 38 , "isvalid" : 1 , "orgName" : "小客车" , "parentId" : 33 } ] } , { "id" : 88 , "isvalid" : 1 , "orgName" : "SUV" , "parentId" : 1 } ] } , { "id" : 2 , "isvalid" : 1 , "orgName" : "自行车" , "parentId" : 0 , "subOrgList"

第四章 递归算法 1209:分数求和

扶醉桌前 提交于 2020-02-22 03:00:35
1209:分数求和 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 4743 通过数: 2670 【题目描述】 输入n个分数并对他们求和,并用最简形式表示。所谓最简形式是指:分子分母的最大公约数为1;若最终结果的分母为1,则直接用整数表示。 如:56、103均是最简形式,而36需要化简为12,31需要化简为3。 分子和分母均不为0,也不为负数。 【输入】 第一行是一个整数n,表示分数个数,1≤n≤10; 接下来n行,每行一个分数,用"p/q"的形式表示,不含空格,p,q均不超过10。 【输出】 输出只有一行,即最终结果的最简形式。若为分数,用"p/q"的形式表示。 【输入样例】 2 1/2 1/3 【输出样例】 5/6 思路:公约数 和公倍数 # include <iostream> # include <cstdio> using namespace std ; int n , p [ 10001 ] , q [ 10001 ] , gbs = 1 , totfz ; int gcd ( int a , int b ) { return b ? gcd ( b , a % b ) : a ; } int lcm ( int a , int b ) { return a * b / gcd ( a , b ) ; } int main ( ) { cin >>