C# For Dummies
Chapter 10. Recursion
1. Write a program to simulate n
nested loops from 1 to n.
Guidelines: Create a recursive method Loops(int k), perform a for-loop from 1 to n and make a recursive call Loops(k-1) in the loop. The bottom of the recursion is when k < 0. Initially invoke Loops(n-1).
Solution:
Link
2. Write a program to generate
all variations with duplicates of
n
elements class
k
.
Example input:
n = 3, k = 2
Example output:
Think about and implement an
iterative algorithm as well.
Guidelines: The
recursive solution is to modify the algorithm for
generating N nested loops. In fact you need
k nested loops from 1 to n.
The
iterative solution is as follows: start from the
first variation in the lexicographical order:
{1, 1, …, 1} k times. To
obtain the next variation, increase the last number. If it becomes greater than
n, change it to 1 and increase the next number on the left. Do the same on the left until the first number goes greater than
n.
Solution:
Link
3. Write a program to generate and print
all combinations with duplicates of
k
elements from a set with
n
elements.
Example input: br />
n = 3, k = 2
Example output:
Think about and implement an
iterative algorithm as well.
Guidelines: Modify the algorithms from
the previous problem and always keep each number equal or greater than the number on the left of it. The easiest way to achieve this is to
generate k nested loops from 1 to n and print only these combinations in which each number is greater or equal than the number on its left. You may optimize this approach to get generate directly an increasing sequence for better performance.
Solution:
Link
4. You are given a
set of strings. Write a
recursive program, which
generates all subsets, consisting exactly
k
strings chosen among the elements of this set.
Example input:
Example output:
Guidelines: Let the strings’ count be
n
. Use the implementation of
k nested loops (recursive or iterative) with additional limitation that
each number is greater than the previous one. Thus you will generate all different subsets of
k
elements in the range
[0…n-1]
. For each set consider the numbers from it as indices in the array of strings and print for each number the corresponding string. For the example above, the set
{0, 2}
corresponds to the strings at position 0 and position 2, i.e.
(test, fun)
.
The
iterative algorithm is similar to the iterative algorithm for generating
n nested loops, but is more complicated because it needs to guarantee that each number is greater than the number on its left.
Solution:
Link
5. Write a
recursive program, which prints
all subsets of a given set of N words.
Example input:
Example output:
Think about and implement an
iterative algorithm as well.
Guidelines: You can
use the previous task and
call it N times in order to generate consequently the empty set
(k=0)
, followed by the all subsets with one element
(k=1)
, all subsets with 2 elements
(k=2)
, all subsets with 3 elements
(k=3)
, etc.
The problem has another
very smart iterative solution: run a
loop from 0 to 2N-1 and convert each of these numbers to
binary numeral system. For example, for
N=3
you will have the following binary representations of the numbers between 0 to
2N-1: 000, 001, 010, 011, 100, 101, 110, 111
Now for each binary representation take those words from the subset for which
have bit 1 on the corresponding position in the binary representation. For instance, for the binary representation \"101\" take the first and the last string (at these positions there is 1) and omit the second string (at this position there is 0). Smart, isn’t it?
Solution:
Link
6. Implement the
merge-sort algorithm recursively. In it the initial array is divided into two equal in size parts, which are sorted (recursively via merge-sort) and after that the two sorted parts are merged in order to get the whole sorted array.
Guidelines: In case you have any difficulties
search in Internet for \"merge sort\". You are going to find hundreds of implementations, including in C#. The challenge is to avoid allocating a new array for the result at each recursive call, because this is inefficient, and to
use only three arrays in the whole program: two arrays to be merged merge and a third for the result from the merging. You will have to implement merging of two ranges of an array into a range of another array.
Solution:
Link
7. Write a recursive program, which generates and prints
all permutations of the numbers 1, 2, …, n
, for a given integer
n
.
Example input:
n = 3
Example output:
Guidelines:
Recursive algorithm: suppose that the method
Perm(k)
permutes in all possible ways the elements of the array
p[]
at positions from 0 to
k-1
(inclusive). Firstly, initialize the array p with the numbers from 1 to N.
Implement recursively Perm(k)
in the following way:
1. If
k==0
, print the current permutation and exit the recursion (bottom of the recursion).
2. Call
Perm(k-1)
.
3. For each position
i
from 0 to
k-1
do the following:
a. Swap
p[i]
with
p[k]
.
b. Recursively call
Perm(k-1)
.
c. Swap back
p[i]
with
p[k]
.
In the beginning call
Perm(k-1)
to start the recursive generation.
Iterative algorithm: Read in Wikipedia how to generate from given permutation the next permutation in the lexicographic order iteratively:
en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order.
Solution:
Link
8. You are given an array of integers and a number
N
. Write a recursive program that finds
all subsets of numbers in the array, which have a
sum N
. For example, if we have the array
{2, 3, 1, -1}
and
N=4
, we can obtain
N=4
as a sum in the following two ways:
4=2+3-1; 4=3+1
.
Guidelines: The problem is not very different from the task with
finding all subsets among a given list of strings. Shall it work fast enough with 500 numbers? Pay attention that we have to print
all subsets with sum N which can be really big amount if
N
is very big and proper numbers exist in the array. For this reason
the task has no efficient solution
Solution:
Link
9. . You are given an array of
positive integers. Write a program that checks whether there is one or more numbers in the array
(subset), whose sum is equal to S. Can you solve the task
efficiently for large arrays?
Guidelines: If we approach the problem by the method of generating of all possibilities, the solution
will not work for more than 20-30 numbers. That’s why we may approach it in a very different way in case the elements of the array are only positive, or are
limited in a certain range (for example
[-50…50]
). Then we could use the following optimized algorithm based on
dynamic programming:
Assume we are given an array of numbers
p[]
. Let’s denote by
possible(k, sum)
whether we could obtain
sum
by using only the numbers first
k numbers (
p[0], p[1], …, p[k]
). Then, the following
recurrent dependencies are valid:
-
possible(0, sum) = true
if
p[0] == sum
-
possible(k, sum) = true
if
possible[k-1, sum] == true
or
possible[k-1, sum-p[k]] == true
The formula above shows that we can obtain
sum
from the elements of the array at positions 0 to
k
if one of the following two statements remains:
- The element
p[k]
does not participate in the sum and the sum is obtained from the rest of the elements (from 0 to
k-1
);
- The element
p[k]
participates in
sum
and the remainder
sum-p[k]
is obtained from the rest of the elements (from 0 to
k-1
).
The implementation is not complex. Just calculate the recursive formulas by
recursive method. We should be careful and not let already calculated values from the two-dimensional array
possible[,]
to be calculated twice. For this purpose we should keep for each possible k and sum the value
possible[k,sum]
. Otherwise the algorithm will not work for more than 20-30 elements.
The regeneration of the numbers, which compose the found sum, may be implemented if we
go backwards from the sum n, obtained from the first
k
numbers. At each step we examine how this sum can be obtained from the first
k–1
numbers (by taking the
kth
number or omitting it).
Bear in mind that in the general case all possible sums of the numbers from the input array may be an awful lot. For instance, possible sums of 50
int
numbers in the range
[Int32.MinValue …Int32.MaxValue]
are enough so that we could not sum them in whatever data structure. If, however, all numbers in the input array are positive (as in our case), we could keep the sums in the range
[1…S]
because from the rest we could not obtain sum
S
by adding one or more numbers from the input array.
If the numbers in the input array are not mandatory positive, but are
limited in a range, then all possible sums are limited in some range too and we could use the algorithm described above. For example, if the range of numbers is from -50 to 50, then the least sum is -50*S and the greatest is 50*S.
If the numbers in the input array are random and not limited in a range, then
the problem has no efficient solution.
You could read more about this classical optimization problem in computer science called “
Subset Sum Problem” in the following article in Wikipedia:
http://en.wikipedia.org/wiki/Subset_sum_problem .
Solution:
Link
10. You are given a
matrix with passable and impassable cells. Write a recursive program that finds
all paths between two cells in the matrix.
Guidelines: Note that you need to find all possible paths (not just one of them) so don’t expect your program to run fast for large input data.
Solution:
Link
← Back