递归

归并排序——Java

拈花ヽ惹草 提交于 2020-01-30 00:18:24
文章目录 归并排序 原地归并的抽象方法 自顶向下的归并排序 自底向上的归并排序 三项优化 归并排序 两个有序数组归并成一个更大的有序数组,就叫归并。 归并排序 是一种递归排序算法,就对一个数组来说,可以先将它(递归地)分成两半分别排序,然后将结果归并起来。 时间复杂度:O(NlogN) 空间复杂度:T(N) 原地归并的抽象方法 两个不同的有序数组如何实现归并? 一个最简单直接地方法就是创建一个最够大的第三数组,然后将两个有序数组的元素从大到小的排到第三数组中,这就叫原地归并。 /** * 原地归并的抽象方法 * 归并,数组两边一定要是有序的 */ public static void merge ( Comparable [ ] a , int lo , int mid , int hi ) { //将a[lo..mid]和a[mid+1..hi]归并 int i = lo , j = mid + 1 ; //将a[lo..hi]复制到aux[lo..hi] for ( int k = lo ; k <= hi ; k ++ ) { aux [ k ] = a [ k ] ; } //归并回到a[lo..hi] for ( int k = lo ; k <= hi ; k ++ ) { if ( i > mid ) { a [ k ] = aux [ j ++ ] ; } else

二叉树的创建与递归和非递归遍历

瘦欲@ 提交于 2020-01-29 23:53:28
二叉树的常规操作就是遍历,这也是二叉树的基本功之一 class TreeNode(): def __init__(self, x): self.val = x self.left = None self.right = None class BinaryTree(object): def __init__(self, pre, tin): self.pre = pre self.tin = tin self.levelTrave = [] # 层次遍历结果 self.preTraveRecur = [] # 前序递归遍历结果 self.preTraveNoRecur = [] # 前序非递归遍历结果 self.inTraveRecur = [] # 中序递归遍历结果 self.inTraveNoRecur = [] # 中序非递归遍历结果 self.postTraveRecur = [] # 后序递归遍历结果 self.postTraveNoRecur = [] # 后序非递归遍历结果 # 利用前序遍历和中序遍历结果重建二叉树 def reConstructBinaryTree(self, pre, tin): # pre为前序遍历结果,tin为中序遍历结果 if len(pre) == 0: return None if len(pre) == 1: return

Java编程的逻辑 (11) - 初识函数

情到浓时终转凉″ 提交于 2020-01-29 21:12:41
本系列文章经补充和完善,已修订整理成书《Java编程的逻辑》,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接 : http://item.jd.com/12299018.html 函数 前面几节我们介绍了数据的基本类型、基本操作和流程控制,使用这些已经可以写不少程序了。 但是如果需要经常做某一个操作,则类似的代码需要重复写很多遍,比如在一个数组中查找某个数,第一次查找一个数,第二次可能查找另一个数,每查一个数,类似的代码都需要重写一遍,很罗嗦。另外,有一些复杂的操作,可能分为很多个步骤,如果都放在一起,则代码难以理解和维护。 计算机程序使用 函数这个概念来解决这个问题,即 使用函数来减少重复代码和分解复杂操作,本节我们就来谈谈Java中的函数,包括函数的基础和一些细节。 定义函数 函数这个概念,我们学数学的时候都接触过,其基本格式是 y = f(x),表示的是x到y的对应关系,给定输入x,经过函数变换 f,输出y。程序中的函数概念与其类似,也有输入、操作、和输出组成,但它表示的一段子程序,这个子程序有一个名字,表示它的目的(类比f),有零个或多个参数(类比x),有可能返回一个结果(类比y)。我们来看两个简单的例子: public static int sum(int a, int b){ int sum = a +

oracle中 connect by prior 递归查询

淺唱寂寞╮ 提交于 2020-01-29 21:10:12
Oracle中start with...connect by prior子句用法 connect by 是结构化查询中用到的,其基本语法是: select ... from tablename start with 条件1 connect by 条件2 where 条件3; 例: select * from table start with org_id = 'HBHqfWGWPy' connect by prior org_id = parent_id; 简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段: org_id,parent_id那么通过表示每一条记录的parent是谁,就可以形成一个树状结构。 用上述语法的查询可以取得这棵树的所有记录。 其中: 条件1 是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。 条件2 是连接条件,其中用PRIOR表示上一条记录,比如 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。 条件3 是过滤条件,用于对返回的所有记录进行过滤。 简单介绍如下: 早扫描树结构表时,需要依此访问树结构的每个节点,一个节点只能访问一次,其访问的步骤如下: 第一步:从根节点开始; 第二步:访问该节点; 第三步

zkw线段树

一世执手 提交于 2020-01-29 21:09:16
zkw线段树是zkw大神搞的自底向上线段树,以常数小,代码短著称。然而zkw大神的原ppt中描述简单,想了好长时间才想粗来。 以下内容针对 区间最小值 ,使用更好理解的递归方式描述。 定义 zkw线段树定义如下: 1. 它是一棵 满二叉树 2. 他的叶节点是一个数 3. 每一个非叶节点是一个数,且这个数是它的两个孩子中的较小值 显然,zkw线段树和普通线段树类似。他的叶节点从左到右是一个数列A1..n,非叶节点存一些信息以便查询区间最小值。 由于它是一个满二叉树,可以用 堆式储存法 储存。特别的,由于叶节点的个数为2的正整数幂,对于数据规模n,叶子节点的实际个数为 2 lg n + 1 , 没有数据的节点用 ∞ 填充 。 性质 不难发现,一棵有tn个节点的满二叉树有tn-1个非叶子节点。所以在堆式结构中,第i个叶子节点的位置是 tree[tn-1+i] 。这是一个很重要的性质,zkw线段树的许多操作是建立在他的基础上的。 由1容易得出,对于树上(堆中)任意一个位置i,如果i是偶数,那么它是一个左孩子;否则是一个右孩子。 1 2 3 4 5 6 7 //显然,所有奇数都是右孩子,偶数都是左孩子 建立数据结构 直接用静态数组建立即可,i的左右孩子分别为 i*2,i*2+1 const int maxn = 100000; // 最多节点数 int tree[maxn*4]; //

二叉树的遍历

醉酒当歌 提交于 2020-01-29 20:47:50
1、二叉树的广度遍历 2、二叉树的深度遍历 二叉树的深度遍历,包括了前序遍历、中序遍历、后续遍历。其命名方式是根节点的遍历顺序, 即:先序遍历:先遍历根节点(根节点->左子树->右子树),即先访问根节点再递归的访问左子树,然后递归的访问右子树。 中序遍历:访问的中间位置为根位置,其主要顺序为(左子树->根节点->右子树),即我们先递归的使用中序遍历访问左子树,让后根节点,然后递归的使用中序遍历访问右子树。 后序遍历:最后访问根节点(左子树->右子树->根节点),即我们先递归的使用后续遍历访问左子树,然后递归的使用后续遍历右子树,最后访问根节点 来源: CSDN 作者: lianchaozhao 链接: https://blog.csdn.net/weixin_40809627/article/details/104105319

二叉树的遍历.队列与栈实现

天大地大妈咪最大 提交于 2020-01-29 20:45:32
树的遍历方法有广度优先(层序遍历),以及深度优先两种方法,分成先序遍历,中序遍历,后序遍历三种。 一.深度优先: 1.递归实现: 先序遍历 输出顺序:根节点,左子树,右子树。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { //如果树非空 printf ( "%d" , BT - > Data ) ; //输出根节点 PreOrderTraversal ( BT - > Left ) ; //继续递归执行其左子树 PreOrderTraversal ( BT - > Right ) ; //继续递归其右子树 } } 中序输出:左子树,根节点,右子树。 只需要将输出语句放到两个递归语句之间即可。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { PreOrderTraversal ( BT - > Left ) ; printf ( "%d" , BT - > Data ) ; PreOrderTraversal ( BT - > Right ) ; } } 后序输出:左子树,右子树,根节点。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { PreOrderTraversal ( BT - > Left ) ;

递归实现排列型枚举

梦想与她 提交于 2020-01-29 18:30:31
问题 K: 递归实现排列型枚举 时间限制: 1 Sec 内存限制: 128 MB [提交] [状态] 题目描述 把 1~n 这 n(n<10) 个整数排成一行后随机打乱顺序,输出所有可能的次序。 输入 一个整数n。 输出 按照从小到大的顺序输出所有方案,每行1个。 首先,同一行相邻两个数用一个空格隔开。其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。 样例输入 Copy 3 样例输出 Copy 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 #include <vector> using namespace std; int n; vector<int> path; vector<int>::iterator iter = path.begin(); void dfs(int u,int state){ if(u == n){ //for(auto x : path) cout<<x<<' '; iter=path.begin(); for(;iter!=path.end();iter++) cout<<*iter<<' '; cout<<endl; return ; } for(int i=0;i<n;i++){ if(!(state>>i&1)){ path.push_back(i+1); dfs(u+1,state|(1<<i));

剑指offer题目解析(附带视频解析链接)

旧时模样 提交于 2020-01-29 16:57:29
写在前面 代码说明 :代码的下载地址: https://github.com/WuNianLuoMeng/Coding 视频说明 :第一次以这样的形式录视频,如果有哪里说的不对,还请各位及时指出,谢谢~~~ 二维数组中的查找 视频链接 方法一: 通过遍历array数组,去查找array数组中有没有target的值。它的时间复杂度是(O(n * m)) public boolean Find ( int target , int [ ] [ ] array ) { for ( int i = 0 ; i < array . length ; i ++ ) { for ( int j = 0 ; j < array [ 0 ] . length ; j ++ ) { if ( array [ i ] [ j ] == target ) return true ; } } return false ; } 方法二(从矩阵的右上角开始找): 设置一个i,j表示所找当前位置,如果说array[i][j] > target大的话,接着就往左找,反之往下找,直到找到array[i][j] == target为止。它的时间复杂度是:O(n + m) public boolean Find ( int target , int [ ] [ ] array ) { int i = 0 ; int j

递归与尾递归

送分小仙女□ 提交于 2020-01-29 16:34:12
1.递归 递归是一个函数直接或间接地调用自身,是为直接或间接递归。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。用递归需要注意以下两点: (1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。 递归一般用于解决三类问题:   (1)数据的定义是按递归定义的。(Fibonacci函数,n的阶乘)   (2)问题解法按递归实现。(回溯)   (3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索) 递归的缺点:   递归解题 相对常用的算法如普通循环等,运行效率较低 。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,因此递归次数过多容易造成 栈溢出 。 代码: int FibonacciRecursive(int n) { if( n < 2) return n; return (FibonacciRecursive(n-1)+FibonacciRecursive(n-2)); } 递归写的代码非常容易懂,完全是根据函数的条件进行选择计算机步骤。例如现在要计算n=5时的值,递归调用过程如下图所示: 2.尾递归 尾递归就是从最后开始计算,