You are on page 1of 4

Data Structures & Algorithms 1st Year Sheet #4 - solution

Cairo University
Faculty of Engineering
Computer Engineering Department
Data Structures and Algorithms
Sheet #4 - solution
Recursion Commented [E1]: First of all, tell them the design steps of
recursive algorithms and that you think about base case and
Part I: Exercises terminating condition separately.
It’s important to show them to students in all solved
1. Consider the following recursive algorithm: problems.
a. Show the output and draw the sequence of recursive calls of the following: Then start directly with the exercises and problems. They’re
chosen in a logical order to make them understand gradually.
i. func (10, 4)
ii. func (4, 4) Commented [E2]:
i.-1
iii. func (4, 7) ii.1
iii.120
Algorithm func (x, y)
//Input: 2 integers x and y func(4, 7)
4* func(5, 7)
if x > y return -1 5* func(6, 7)
elseif x = y return 1 6* func(7*7)
else return x * func (x + 1, y) 1 then UP ^

2. Consider the following recursive algorithm: Commented [E3]:


a. Show the output and draw the sequence of recursive calls of the following: Sum of cubes

i. S(1)
ii. S(5)
b. What does the algorithm compute?
Algorithm S(n)
//Input: a positive integer n
if n = 1 return 1
else return S(n-1) + n*n*n
3. Consider the following recursive algorithm: Commented [E4]:
a. Show the output and draw the sequence of recursive calls of the following: Algorithm: Minimum.
Decrease-by-1 algorithm (1 recursive call).
i. Riddle1([2, 3], 2)
ii. Riddle1([3, 5, 4, 1, 2], 5)
b. What does the algorithm compute?
Algorithm Riddle1(A, n)
//Input: An array A of real numbers of length n
if n = 1 return A[0]
temp←Riddle1(A, n-1)
if temp ≤ A[n − 1] return temp
else return A[n − 1]
4. Consider the following recursive algorithm: Commented [E5]:
a. Show the output and draw the sequence of recursive calls of the following: Algorithm: Minimum too.
Divide-and-conquer algorithm (more than 1 recursive calls to
i. Riddle2([2, 5, 3, 6], 0, 3) calc the answer).
ii. Riddle2([3, 5, 4, 1, 2], 0, 4)
b. What does the algorithm compute?
Algorithm Riddle2(A, first, last)
//Input: An array A of real numbers and 2 integers first and last
if first = last return A[first]
mid = (first+last)/2
temp1←Riddle2(A, first, mid)
temp2←Riddle2(A, mid + 1, last)
if temp1 ≤ temp2 return temp1
else return temp2

CMP 102 & CMP N102 1/4 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

5. Does it matter where you position your recursive call in your function? Commented [M. Ismail6]:
Given two versions of recursive function that searches for a given value in a linked list; what RecSearch1 is better as RecSearch2 is called N times (where
N is list length) no matter where the searched element is.
is the difference between the two functions? Which one is better and why? RecSearch1 is called only until the searched element is found
Test the two functions if linked list L = [10]→[12] → [4]→[7]→[56]→[9]→# and val=12.
Node* RecSearch1(Node *L, int val) Node* RecSearch2(Node *L, int val)
{ {
if(L == NULL) return NULL; if(L == NULL) return NULL;
if(L->data == val) return L;
Node *P = RecSearch2(L->Next, val);
return RecSearch1(L->Next, val); if( P != NULL) return P;
} if(L->data == val) return L;
else return NULL;
}

Part II: Problems Commented [E7]: Part II


Common mistake:
1. Write a recursive a logarithm to get the sum of series 1+2+3+4+…+n. forget to write return before the recursive call even if the
You only need to take n (not storing numbers in array) function is not void.
int Sum(int n) //Similar to n! problem OR
always writing return recall(…); even if the function is void.
{
if(n == 0) return 0;
return n+Sum(n-1);
}

2. Write a recursive algorithm to add the first n elements of the series:1+1/2+1/3+1/4+1/5+...+1/n Commented [E8]: Problem [2]
Similar to problem 1
3. Write a recursive algorithm that calculates and returns the sum of array elements.
int ArrSum(int *arr, int size)
{
If(size == 1) return A[0];
Return A[0]+ ArrSum(&A[1], size-1)
}
=======================
Another solution
int ArrSum(int *A, int size)
{
If(size==1) return A[0];
Return A[size-1] + ArrSum(A, size-1)
}
4. Write a recursive algorithm to count number of occurrences of a value in an array.

5. Write a recursive algorithm that calculates and returns the length of a linked list.
int GetLenght(Node *L)
{
If(L==NULL) return 0;
Return 1+ GetLenght(L→next);
}
6. Write a recursive algorithm to compute the sum of even numbers in a linked list.

7. Write a recursive algorithm to print a linked list in a forward order. What are the modifications to print Commented [M. Ismail9]: Problem [7]
it reversed? Forward 
cout head data BEFORE the recursive call
void Print(Node * L) Reverse 
{ if(L == NULL) return; cout head data AFTER the recursive call
cout≪L→data;
Print(L→next);
}
8. Write a recursive algorithm to print numbers read from keyboard in a forward order. What are the Commented [E10]: Problem[8]
modifications to print them reversed? (Note: don’t store numbers in an array; just print) Same as 7 but void function with no return

CMP 102 & CMP N102 2/4 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

9. Compare the recursive solution of print reverse of problem 7 and 8 with the stack solution. Commented [E11]: Problem[9]
Stack vs Recursive:
Stack  extra memory (not in-place)
10. Compare the recursive solution of print forward of problem 7 and 8 with the iterative solution. Recursive  overhead of recursive calls
Commented [E12]: Problem[10]
11. Write a recursive algorithm that returns the index of the first occurrence of an element in array if Iterative vs Recursive:
found and -1 if not found. What are the modifications to return the index of last occurrence? Recursive  overhead of the recursive but less and simpler
int FirstOcc(int* A, int n, int x) Another solution for problem 11. FrstOcc implementation.
{ that scans the array in forward direction But this doesn’t mean that iterative is always better or the
opposite.
if(n == 0) return -1; Better to use recursion if:
if(A[n-1] == x) int FrstOcc(int *A, int n, int x) 1-used alg or ds is usually solved by recursion, ex: trees
{ { 2-recursive algorithm is much shorter than the iterative
int ind = LastOcc(A, n-1, x); if(n<= 0 ) return -1; With the condition that the recursive algorithm should run in
time and space accepted to your application.
if(ind != -1 && ind < n-1) return ind; if(A[0] == x ) return 0;
else return n-1; int ind = FrstOcc(A+1, n-1, x);
} if(ind != -1) return ind+1;
} return -1;
}
int LastOcc(int* A, int n, int x)
{
if(n == 0) return -1;
if(A[n-1] == x) return n-1;
else return LastOcc(A, n-1, x);
}

12. Write a recursive algorithm to check whether a linked list is sorted in an increasing order. Commented [E13]: Problem[12]
bool isAsc(node* head) Common mistakes of the bold line above:
1- write the func call without “return”
{ 2- return true instead
if(!head || !head->next) return true; 3- return isAsc(head->next->next);
if(head->data < head->next->data) Note:
return isAsc(head->next); Concerning linked list special cases, always when you write
about xxx->data or xxx->next, make sure before it that xxx
else return false; not null (add a special case condition if needed).
} Above, before writing:
(head->data < head->next->data)
The special condition in the 1st line check if any is null.
13. Write a recursive algorithm that checks whether a string is a substring of another string.
bool Find(string s, int start, int last, string sub, int m) Commented [E14]: Problem [13]
Iteration inside recursion.
{
int n = last-start+1;
if(m > n) return false;
for(int i = 0; i<m; i++)
{
if(s[start+i] != sub[i])
return Find(s, start+1, last, sub, m); //Note: start+1 not start+i in the recursive call
}
return true;
}
Another solution for problem 13 if we will use char* not string
bool RecSubString(char *s, char *sub)
{
int subLen = strlen(sub);
if(strlen(s) < subLen ) return false;
int i;
for(i=0; i<subLen ; i++)
if(s[i] != sub[i] ) break;
if(i == subLen ) return true;

return RecSubString(s+1, sub);


}

CMP 102 & CMP N102 3/4 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

14. Write a recursive algorithm that converts a string of numerals to an integer. For example, “43567” will Commented [E15]: Problem [14]
be converted to 43567. (Hint: 43567 = 4*10000+3*1000+5*100+6*10+7*1 ) 43567 = 40000+3000+500+60+7

15. Write a recursive C++ function to get the length of a circular linked list (Hint: you should send the Commented [E16]: Problem [15]
head of the original list too in each call; 2 inputs) A simple solution for them now (without using static vars),
int Len(node* head, node* ptr)
{
16. Write a recursive algorithm that reverses a linked list (without using new nodes). (Hint: make each if(!head || ptr == head) return 0;
next pointer points to previous. It’s simple if you think recursively) if(!ptr) ptr = head;
return 1 + Len(head, ptr->next);
}
17. Solve palindrome problem (stack problem 2, sheet 5) using recursion. (Hint: check the first To get the length of a circular linked list, you have to call Len
character with the last character) that way:
int x = Len(head, null);

18. Solve Josephus problem (problem 11, sheet 3) using recursion. Commented [E17]: Problem [16]
The idea of the algorithm:
1- divide the list in two parts
- first node and rest of the linked list.
2- call reverse for the rest of the linked list.
3- link rest to first.
4- fix head pointer
The full solution is here:
http://www.geeksforgeeks.org/write-a-function-to-reverse-the-
nodes-of-a-linked-list/

Commented [E18]: Problem [17]


The idea of the algorithm:
-compare the first char with the last char, if not equal return
false else return func (s, first+1, last-1)
-stops if first = last.
The problem is reduced each call by 2 chars.

CMP 102 & CMP N102 4/4 Spring 2018

You might also like