Chapter 2: Recursion & Backtracking

Chapter 2: Recursion and Backtracking

1. Recursion

Any function which calls itself is called recursive. A recursive method solves a problem by calling a copy of itself on a smaller problem. Recursion is most useful for tasks that can be defined in terms of similar subtasks.

Recursion code is generally shorter and easier to write than iterative code. Generally, loops are turned into recursive function when they are compiled or interpreted. Each recursive call makes a new copy of that method (actually only the variables) in memory. Once a method ends (that is, return some data), the copy of that returning method is removed from memory.

Recursive algorithm have two types of cases, recursive cases and base cases. Every recursive function case must terminate at a base case. Generally, iterative solutions are more efficient than recursive solutions (due to the overhead of function calls). A recursive algorithm can be implemented without recursive function calls using a stack, but it’s usually more trouble than its worth. That means any problem that can be solved recursively can also be solved iteratively.


2. Recursion versus Iteration

Recursion

  • Terminates when a base case is reached.
  • Each recursive call requires extra space on the stack frame (memory).
  • If we get infinite recursion, the program may run out of memory and result in stack overflow.
  • Solutions to some problems are easier to formulate recursively.

Iteration

  • Terminates when a condition is proven to be false.
  • Each iteration does not require extra space.
  • An infinite loop could loop forever since there is no extra memory being created.
  • Iterative solutions to a problem may not always be as obvious as a recursive solution.

3. Example Algorithms of Recursion

  • Fibonacci Series, Factorial Finding
  • Merge Sort, Quick Sort
  • Binary Search
  • Tree Traversals and many tree problems: InOrder, PreOrder, PostOrder
  • Graph Traversals: DFS (Depth First Search) and BFS (Breadth First Search)
  • Dynamic Programming Examples
  • Divide and Conquer Algorithms
  • Towers of Hanoi
  • Backtracking Algorithm

4. Recursion: Problems & Solutions

Pro 1: Discuss Towers of Hanoi puzzle

solution: The Towers of Hanoi consists of three rods and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks on one rod in ascending order of size, the smallest at the top thus making a conical shape. The objective is to move the entire stack to another rod, satisfying the following rules: Only one disk may be moved at a time; Each move consists of taking the upper disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod; No disk may be paced on top of a smaller disk.

Algorithm:

  • Move the top n-1 disks from Source to Auxiliary tower,
  • Move the nth disk from Source to Destination tower,
  • Move the n-1 disks from Auxiliary tower to Destination tower.
  • Transferring the top n-1 disks from Source to Auxiliary tower can again be thought of as a fresh problem and can be solved in the same manner. Once we solve with three disks, we can solve it with any number of disks with the above algorithm.
void TowerOfHanoi(int n, char sour, char dest, char auxi){
	/*if only 1 disk, make the move and return*/
	if(n==1){
		printf("Move disk 1 from peg %c to peg %c", sour, dest);
		return;
	}
	/*move top n-1 disk from A to B using C as auxiliary*/
	TowerOfHanoi(n-1, sour, auxi, dest);
	/*move remaining disk from A to C*/
	printf("\n Move disk %d from peg %c to peg %c", n, sour, dest);
	/*move n-1 disks from B to C using A as auxiliary*/
	TowersOfHanoi(n-1, auxi,dest, sour);
}

Pro 2: Given an array check whether the array is sorted order with recursion

solution:

int isArrayInSortedOrder(int A[], int n){
	if(n==1) return 1;
	return (A[n-1]<A[n-2]) ? 0 :isArrayInSortedOrder(A, A-1);
}

Time Complexity: O(n). Space Complexity: O(n) for recursive stack space.


5. Backtracking

Backtracking is an improvement of the brute force approach. It systematically searches for a solution to a problem among all available options. It is a form of recursion and can be thought of as a selective tree/graph traversal method. At each node, we eliminate choices that are obviously not possible and proceed to recursively check only those that have potential. Backtracking speeds the exhaustive search by pruning.


6. Example Algorithm of Backtracking

  • Binary String: Generating all binary strings
  • Generating k-ary Strings
  • N-Queens Problem
  • The Knapsack Problem
  • Generalized Strings
  • Hamiltonian Cycles
  • Graph Coloring Problems

7. Backtracking: Problems & Solutions

Pro 3: Generate all the strings of n bits

solution:

void Binary(int n){
	if(n<1) printf("%s", A);		//Assume array A is a global varible. A[0..n-1] array of size n. 
	else{
		A[n-1]=0;
		Binary(n-1);
		A[n-1]=1;
		Binary(n-1);
	}
}	

Pro 4: Generate all strings of length n drawn from 0…k-1

void k_string(int n, int k){
	if(n<1) printf("%s",A);
	else{
		for(int j=0; j<k; j++){
			A[n-1]=j;
			k_string(n-1,k);
		}
	}
}	

Pro 5: Finding the length of connected cells of 1s (regions) in an matrix of Os and 1s

Given a matrix, each of which may be 1 or 0. The filled cells that are connected form a region. Two cells are said to be connected if they are adjacent to each other horizontally, vertically or diagonally.

Solution: For each location traverse in all 8 directions and in each of those directions keep track of maximum region found.

int getval(int (*A)[5], int j, int j, int L, int H){
	if(i<0 || i>=L|| j<0 || j>=H) return 0;
	else return A[i][j];
}

void findMaxBlock(int (*A)[5], int r, int c, int L, int H, int size, bool **cntarr, int &maxsize){
	if(r>=L|| c>H) return;
	cntarr[r][c]=true;
	size++;
	if(size>maxsize) maxsize=size;

	int direction[][2]={{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
	for(int i=0; i<8; i++){
		int newi=r+direction[i][0];
		int newj=c+direction[i][1];
		int val=getval(A, newi, newj, L, H);
		if(val>0 && (cntarr[newi][newj]==false)){
			findMaxBlock(A, newi, newj, L, H, size, cntarr, maxsize);
		}
	}
	cntarr[r][c]=false;
}

int getMaxOnes(int (*A)[5], int rmax, int colmax){
	int maxsize=0;
	int size=0;
	bool **cntarr=create2darr(rmax,colmax);
	for(int i=0; i<rmax; i++){
		for(int j=0; j<colmax; j++){
			if(A[i][j]==1)
				findMaxBlock(A, i, j, rmax, colmax, 0, cntarr, maxsize);
		}
	}
	return maxsize;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 错误:在加载“cv2”二进制扩展期间检测到递归。请检查OpenCV安装。 这个错误通常是由于OpenCV安装不正确或不完整引起的。您可以尝试重新安装OpenCV或检查您的安装是否正确。如果问题仍然存在,请尝试卸载OpenCV并重新安装。 ### 回答2: 这个报错意味着系统在加载“cv2”二进制扩展程序时遇到了递归,可能是因为OpenCV安装存在问题。递归是程序调用自身的过程,因此报错表明在尝试加载cv2时遇到了类似调用自身的情况。 要解决这个问题,需要首先检查系统中安装的OpenCV是否正确。OpenCV是一个开源计算机视觉库,主要用于图像和视频处理,其安装过程可能比较繁琐,需要注意安装的版本、路径、依赖库等。检查OpenCV是否正确安装,可以尝试运行一些其他的OpenCV程序或者检查OpenCV的路径是否正确。如果OpenCV安装出现问题,可能会导致cv2的二进制扩展程序也出现问题,从而导致递归加载。 另外,可能也需要检查是否存在其他环境变量或库冲突的问题。在Python应用程序中,会使用一些第三方库和模块,如果存在冲突可能会导致错误。可能需要检查系统中已安装的库以及它们的版本,并确保它们不会与OpenCV或cv2冲突。 总之,要解决这个问题,需要仔细排查各种可能的原因,从而找到并解决问题。可能需要花费一定的时间和精力,但这也是程序开发中经常需要面对的挑战之一。 ### 回答3: 在使用Python语言时,有时候会遇到一些错误信息,其中一个比较常见的错误信息就是“error: recursion is detected during loading of "cv2" binary extensions. check opencv installation.”这个错误信息的意思是在加载“cv2”二进制扩展时发现了递归,需要检查OpenCV的安装情况。 要想了解这个错误信息的原因,我们需要先了解一下递归的概念。递归是一种常见的编程技巧,它是指函数直接或间接地调用自身,这就导致函数在执行过程中会多次调用自己。但递归的使用也容易因为没能正确终止递归,导致进入死循环,最终导致程序崩溃。 这个“cv2”二进制扩展本身就是OpenCV(Open Source Computer Vision Library)库的核心功能模块,这个库是一个开源的计算机视觉和机器学习软件库,这个库的官方安装方式中,常常是通过源代码编译安装,这个库底层使用C++编写,而Python调用OpenCV的接口时,需要用到一个名为“cv2”的二进制扩展,这个“cv2”二进制扩展是经过编译后的动态链接库,它使用了OpenCV内部的算法和数据结构。 当出现“error: recursion is detected during loading of "cv2" binary extensions. check opencv installation.”这个错误信息时,几乎可以肯定是因为所加载的“cv2”二进制扩展存在问题,可能是这个二进制扩展中的某个方法或某个逻辑出现了递归调用,导致了无限递归,直到内存耗尽或者栈溢出。为了解决这个问题,我们需要检查OpenCV的安装情况,确认所使用的OpenCV版本正确、完整。同时,也可以尝试使用其他方式调用OpenCV的接口、或者重新编译安装OpenCV库来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值