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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值