I have written a program to print all the permutations of the string using backtracking method.
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "ABC";
permute(a, 0, 2);
getchar();
return 0;
}
What would be time complexity here.Isn't it o(n2).How to check the time complexity in case of recursion? Correct me if I am wrong.
Thanks.
The complexity is O(N*N!), You have N! permutations, and you get all of them.
In addition, each permutation requires you to print it, which is O(N) - so totaling in O(N*N!)
My answer is going to focus on methodology since that's what the explicit question is about. For the answer to this specific problem see others' answer such as amit's.
When you are trying to evaluate complexity on algorithms with recursion, you should start counting just as you would with an iterative one. However, when you encounter recursive calls, you don't know yet what the exact cost is. Just write the cost of the line as a function and still count the number of times it's going to run.
For example (Note that this code is dumb, it's just here for the example and does not do anything meaningful - feel free to edit and replace it with something better as long as it keeps the main point):
int f(int n){ //Note total cost as C(n)
if(n==1) return 0; //Runs once, constant cost
int i;
int result = 0; //Runs once, constant cost
for(i=0;i<n;i++){
int j;
result += i; //Runs n times, constant cost
for(j=0;j<n;j++){
result+=i*j; //Runs n^2 times, constant cost
}
}
result+= f(n/2); //Runs once, cost C(n/2)
return result;
}
Adding it up, you end up with a recursive formula like C(n) = n^2 + n + 1 + C(n/2) and C(1) = 1. The next step is to try and change it to bound it by a direct expression. From there depending on your formula you can apply many different mathematical tricks.
For our example:
For n>=2: C(n) <= 2n^2 + C(n/2)
since C is monotone, let's consider C'(p)= C(2^p):
C'(p)<= 2*2^2p + C'(p-1)
which is a typical sum expression (not convenient to write here so let's skip to next step), that we can bound: C'(p)<=2p*2^2p + C'(0)
turning back to C(n)<=2*log(n)*n^2 + C(1)
Hence runtime in O(log n * n^2)
The exact number of permutations via this program is (for a string of length N)
start : N p. starting each N-1 p. etc...
number of permutations is N + N(N-1) + N(N-1)(N-2) + ... + N(N-1)...(2) (ends with 2 since the next call just returns)
or N(1+(N-1)(1+(N-2)(1+(N-3)(1+...3(1+2)...))))
Which is roughly 2N!
Adding a counter in the for loop (removing the printf) matches the formula
N=3 : 9
N=4 : 40
N=5 : 205
N=6 : 1236
...
The time complexity is O(N!)
Related
This is my idea of solving 'nth term of fibonacci series with least processing power'-
int fibo(int n, int a, int b){
return (n>0) ? fibo(n-1, b, a+b) : a;
}
main(){
printf("5th term of fibo is %d", fibo(5 - 1, 0, 1));
}
To print all the terms, till nth term,
int fibo(int n, int a, int b){
printf("%d ", a);
return (n>0)? fibo(n-1, b, a+b): a;
}
I showed this code to my university professor and as per her, this is a wrong approach to solve Fibonacci problem as this does not abstract the method. I should have the function to be called as fibo(n) and not fibo(n, 0, 1). This wasn't a satisfactory answer to me, so I thought of asking experts on SOF.
It has its own advantage over traditional methods of solving Fibonacci problems. The technique where we employ two parallel recursions to get nth term of Fibonacci (fibo(n-1) + fibo(n-2)) might be slow to give 100th term of the series whereas my technique will be lot faster even in the worst scenario.
To abstract it, I can use default parameters but it isn't the case with C. Although I can use something like -
int fibo(int n){return fiboN(n - 1, 0, 1);}
int fiboN(int n, int a, int b){return (n>0)? fiboN(n-1, b, a+b) : a;}
But will it be enough to abstract the whole idea? How should I convince others that the approach isn't wrong (although bit vague)?
(I know, this isn't sort of question that I should I ask on SOF but I just wanted to get advice from experts here.)
With the understanding that the base case in your recursion should be a rather than 0, this seems to me to be an excellent (although not optimal) solution. The recursion in that function is tail-recursion, so a good compiler will be able to avoid stack growth making the function O(1) soace and O(n) time (ignoring the rapid growth in the size of the numbers).
Your professor is correct that the caller should not have to deal with the correct initialisation. So you should provide an external wrapper which avoids the need to fill in the values.
int fibo(int n, int a, int b) {
return n > 0 ? fibo(b, a + b) : a;
}
int fib(int n) { return fibo(n, 0, 1); }
However, it could also be useful to provide and document the more general interface, in case the caller actually wants to vary the initial values.
By the way, there is a faster computation technique, based on the recurrence
fib(a + b - 1) = f(a)f(b) + f(a - 1)f(b - 1)
Replacing b with b + 1 yields:
fib(a + b) = f(a)f(b + 1) + f(a - 1)f(b)
Together, those formulas let us compute:
fib(2n - 1) = fib(n + n - 1)
= fib(n)² + fib(n - 1)²
fib(2n) = fib(n + n)
= fib(n)fib(n + 1) + fib(n - 1)fib(n)
= fib(n)² + 2fib(n)fib(n - 1)
This allows the computation to be performed in O(log n) steps, with each step producing two consecutive values.
Your result will be 0, with your approaches. You just go in recursion, until n=0 and at that point return 0. But you have also to check when n==1 and you should return 1; Also you have values a and b and you do nothing with them.
i would suggest to look at the following recursive function, maybe it will help to fix yours:
int fibo(int n){
if(n < 2){
return n;
}
else
{
return (fibo(n-1) + fibo(n-2));
}
}
It's a classical problem in studying recursion.
EDIT1: According to #Ely suggest, bellow is an optimized recursion, with memorization technique. When one value from the list is calculated, it will not be recalculated again as in first example, but it will be stored in the array and taken from that array whenever is required:
const int MAX_FIB_NUMBER = 10;
int storeCalculatedValues[MAX_FIB_NUMBER] = {0};
int fibo(int n){
if(storeCalculatedValues[n] > 0)
{
return storeCalculatedValues[n];
}
if(n < 2){
storeCalculatedValues[n] = n;
}
else
{
storeCalculatedValues[n] = (fibo(n-1) + fibo(n-2));
}
return storeCalculatedValues[n];
}
Using recursion and with a goal of least processing power, an approach to solve fibonacci() is to have each call return 2 values. Maybe one via a return value and another via a int * parameter.
The usual idea with recursion is to have a a top level function perform a one-time preparation and check of parameters followed by a local helper function written in a lean fashion.
The below follows OP's idea of a int fibo(int n) and a helper one int fiboN(int n, additional parameters)
The recursion depth is O(n) and the memory usage is also O(n).
static int fib1h(int n, int *previous) {
if (n < 2) {
*previous = n-1;
return n;
}
int t;
int sum = fib1h(n-1, &t);
*previous = sum;
return sum + t;
}
int fibo1(int n) {
assert(n >= 0); // Handle negatives in some fashion
int t;
return fib1h(n, &t);
}
#include <stdio.h>
int fibo(int n);//declaring the function.
int main()
{
int m;
printf("Enter the number of terms you wanna:\n");
scanf("%i", &m);
fibo(m);
for(int i=0;i<m;i++){
printf("%i,",fibo(i)); /*calling the function with the help of loop to get all terms */
}
return 0;
}
int fibo(int n)
{
if(n==0){
return 0;
}
if(n==1){
return 1;
}
if (n > 1)
{
int nextTerm;
nextTerm = fibo(n - 2) + fibo(n - 1); /*recursive case,function calling itself.*/
return nextTerm;
}
}
solving 'nth term of fibonacci series with least processing power'
I probably do not need to explain to you the recurrence relation of a Fibonacci number. Though your professor have given you a good hint.
Abstract away details. She is right. If you want the nth Fibonacci number it suffices to merely tell the program just that: Fibonacci(n)
Since you aim for least processing power your professor's hint is also suitable for a technique called memoization, which basically means if you calculated the nth Fibonacci number once, just reuse the result; no need to redo a calculation. In the article you find an example for the factorial number.
For this you may want to consider a data structure in which you store the nth Fibonacci number; if that memory has already a Fibonacci number just retrieve it, otherwise store the calculated Fibonacci number in it.
By the way, didactically not helpful, but interesting: There exists also a closed form expression for the nth Fibonacci number.
This wasn't a satisfactory answer to me, so I thought of asking
experts on SOF.
"Uh, you do not consider your professor an expert?" was my first thought.
As a side note, you can do the fibonacci problem pretty much without recursion, making it the fastest I know approach. The code is in java though:
public int fibFor() {
int sum = 0;
int left = 0;
int right = 1;
for (int i = 2; i <= n; i++) {
sum = left + right;
left = right;
right = sum;
}
return sum;
}
Although #rici 's answer is mostly satisfactory but I just wanted to share what I learnt solving this problem. So here's my understanding on finding fibonacci using recursion-
The traditional implementation fibo(n) { return (n < 2) n : fibo(n-1) + fibo(n-2);} is a lot inefficient in terms of time and space requirements both. This unnecessarily builds stack. It requires O(n) Stack space and O(rn) time, where r = (√5 + 1)/2.
With memoization technique as suggested in #Simion 's answer, we just create a permanent stack instead of dynamic stack created by compiler at run time. So memory requirement remains same but time complexity reduces in amortized way. But is not helpful if we require to use it only the once.
The Approach I suggested in my question requires O(1) space and O(n) time. Time requirement can also be reduced here using same memoization technique in amortized way.
From #rici 's post, fib(2n) = fib(n)² + 2fib(n)fib(n - 1), as he suggests the time complexity reduces to O(log n) and I suppose, the stack growth is still O(n).
So my conclusion is, if I did proper research, time complexity and space requirement both cannot be reduced simultaneously using recursion computation. To achieve both, the alternatives could be using iteration, Matrix exponentiation or fast doubling.
I have the following problem:
The point (a) was easy, here is my solution:
#include <stdio.h>
#include <string.h>
#define MAX_DIGITS 1000000
char conjugateDigit(char digit)
{
if(digit == '1')
return '2';
else
return '1';
}
void conjugateChunk(char* chunk, char* result, int size)
{
int i = 0;
for(; i < size; ++i)
{
result[i] = conjugateDigit(chunk[i]);
}
result[i] = '\0';
}
void displaySequence(int n)
{
// +1 for '\0'
char result[MAX_DIGITS + 1];
// In this variable I store temporally the conjugates at each iteration.
// Since every component of the sequence is 1/4 the size of the sequence
// the length of `tmp` will be MAX_DIGITS / 4 + the string terminator.
char tmp[(MAX_DIGITS / 4) + 1];
// There I assing the basic value to the sequence
strcpy(result, "1221");
// The initial value of k will be 4, since the base sequence has ethe length
// 4. We can see that at each step the size of the sequence 4 times bigger
// than the previous one.
for(int k = 4; k < n; k *= 4)
{
// We conjugate the first part of the sequence.
conjugateChunk(result, tmp, k);
// We will concatenate the conjugate 2 time to the original sequence
strcat(result, tmp);
strcat(result, tmp);
// Now we conjugate the conjugate in order to get the first part.
conjugateChunk(tmp, tmp, k);
strcat(result, tmp);
}
for(int i = 0; i < n; ++i)
{
printf("%c", result[i]);
}
printf("\n");
}
int main()
{
int n;
printf("Insert n: ");
scanf("%d", &n);
printf("The result is: ");
displaySequence(n);
return 0;
}
But for the point b I have to generate the n-th digit in logarithmic time. I have no idea how to do it. I have tried to find a mathematical property of that sequence, but I failed. Can you help me please? It is not the solution itself that really matters, but how do you tackle this kind of problems in a short amount of time.
This problem was given last year (in 2014) at the admission exam at the Faculty of Mathematics and Computer Science at the University of Bucharest.
Suppose you define d_ij as the value of the ith digit in s_j.
Note that for a fixed i, d_ij is defined only for large enough values of j (at first, s_j is not large enough).
Now you should be able to prove to yourself the two following things:
once d_ij is defined for some j, it will never change as j increases (hint: induction).
For a fixed i, d_ij is defined for j logarithmic in i (hint: how does the length of s_j increase as a function of j?).
Combining this with the first item, which you solved, should give you the result along with the complexity proof.
There is a simple programming solution, the key is to use recursion.
Firstly determine the minimal k that the length of s_k is more than n, so that n-th digit exists in s_k. According to a definition, s_k can be split into 4 equal-length parts. You can easily determine into which part the n-th symbol falls, and what is the number of this n-th symbol within that part --- say that n-th symbol in the whole string is n'-th within this part. This part is either s_{k-1}, either inv(s_{k-1}). In any case you recursively determine what is n'-th symbol within that s_{k-1}, and then, if needed, invert it.
The digits up to 4^k are used to determine the digts up to 4^(k+1). This suggests writing n in base 4.
Consider the binary expansion of n where we pair digits together, or equivalently the base 4 expansion where we write 0=(00), 1=(01), 2=(10), and 3=(11).
Let f(n) = +1 if the nth digit is 1, and -1 if the nth digit is 2, where the sequence starts at index 0 so f(0)=1, f(1)=-1, f(2)-1, f(3)=1. This index is one lower than the index starting from 1 used to compute the examples in the question. The 0-based nth digit is (3-f(n))/2. If you start the indices at 1, the nth digit is (3-f(n-1))/2.
f((00)n) = f(n).
f((01)n) = -f(n).
f((10)n) = -f(n).
f((11)n) = f(n).
You can use these to compute f recursively, but since it is a back-recursion you might as well compute f iteratively. f(n) is (-1)^(binary weight of n) = (-1)^(sum of the binary digits of n).
See the Thue-Morse sequence.
I am trying to make from f_rec (recursive function) to f_iter (iterative function) but I can't.
(My logic was to create a loop to calculate the results of f_rec(n-1).
int f_rec(int n)
{
if(n>=3)
return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
else
return 1;
}
int f_iter(int n)
{
}
I also think that my time complexity for the f_rec is 3^n , please correct me if I'm wrong.
Thank you
There are two options:
1) Use the discrete math lessons and derive the formula. The complexity (well if #Sasha mentioned it) will be O(1) for both memory and algorithm. No loops, no recursion, just the formula.
At first you need to find the characteristic polynomial and calculate its roots. Let's asssume that our roots are r1, r2, r3, r4. Then the n'th element is F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n, where A, B, C, D are some unknown coefficients. You can find these coefficients using your initial conditions (F(n) = 1 for n <= 3).
I can explain it on russian if you need.
2) Use additional variables to store intermediate values. Just like #6052 have answered (he has answered really fast :) ).
You can always calculate the newest value from the last three. Just start calculating from the beginning and always save the last three:
int f_iter (int n) {
int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++
for (int i = 3; i <= n; ++i) {
int new_value = last3[0] + 2 * last3[1] + last3[2];
last3[0] = last3[1];
last3[1] = last3[2];
last3[2] = new_value;
}
return last3[2];
}
This solution need O(1) memory and O(n) runtime. There might exist a formula that calculates this in O(1) (there most likely is), but I guess for the sake of demonstrating the iteration technique, this is the way to go.
Your solution has exponential runtime: Every additional level spawns three evaluations, so you end up with O(3^n) operations and stack-memory.
The following is the idea
int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */
for(i=4;i<=n;i++)
{
int next=first+2*second+third;
first=second;
second=third;
third=next;
}
cout<<"The answer is "<<next<<endl;
Memory is O(1) and time is O(n).
EDIT
Your recursive function is indeed exponential in time , to keep it linear you can make use
of an array F[n], and use memoization. First initialize F[] as -1.
int f_rec(int n)
{
if(n>=3)
{
if(F[n]!=-1)return F[n];
F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
return F[n];
}
else
return 1;
}
Just keep three variables and roll them over
start with a, b and c all equal to 1
at each step new_a is a + 2*b + c
roll over: new_c is b, new_b is a
repeat the required number of steps
A bit of an overkill, but this can be further optimized by letting the what the variables represent change in an unfolded loop, combined with (link) Duff's device to enter the loop:
int f_iter(int n){
int a=1, b=1, c=1;
if(n < 3)
return(1);
switch(n%3){
for( ; n > 2; n -= 3){
case 2:
b = c + 2*a + b;
case 1:
a = b + 2*c + a;
case 0:
c = a + 2*b + c;
}
}
return c;
}
So I just stared programming in C a few days ago and I have this program which takes an unsorted file full of integers, sorts it using quicksort
1st algorithm
Any suggestions on what I have done wrong in this?
From what you have described, it sounds like you are almost there. You are attempting to get the first element of a collection that has a value equal to (or just greather than) 90% of all the other members of the collection. You have already done the sort. The rest should be simply following these steps (if I have understood your question):
1) sort collection into an into array (you've already done this I think)
2) count numbers in collection, store in float n; //number of elements in collection
3) index through sorted array to the 0.9*n th element, (pick first one beyond that point not a duplicate of previous)
4) display results
Here is an implementation (sort of, I did not store n) of what I have described: (ignore the random number generator, et al., it is just a fast way to get an array)
#include <ansi_c.h>
#include <windows.h>
int randomGenerator(int min, int max);
int NotUsedRecently (int number);
int cmpfunc (const void * a, const void * b);
int main(void)
{
int array[1000];
int i;
for(i=0;i<1000;i++)
{
array[i]=randomGenerator(1, 1000);
Sleep(1);
}
//sort array
qsort(array, 1000, sizeof(int), cmpfunc);
//pick the first non repeat 90th percent and print
for(i=900;i<999;i++)
{
if(array[i+1] != array[i])
{
printf("this is the first number meeting criteria: %d", array[i+1]);
break;
}
}
getchar();
return 0;
}
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
srand(clock());
while(trying)
{
random = (rand()/32767.0)*(max+1);
(random >= min) ? (trying = 0) : (trying = 1);
}
return random;
}
And here is the output for my first randomly generated array (centering around the 90th percentile), compared against what the algorithm selected: Column on left is the element number, on the right is the sorted list of randomly generated integers. (notice it skips the repeats to ensure smallest value past 90%)
In summary: As I said, I think you are already, almost there. Notice how similar this section of my code is to yours:
You have something already, very similar. Just modify it to start looking at 90% index of the array (whatever that is), then just pick the first value that is not equal to the previous.
One issue in your code is that you need a break case for your second algorithm, once you find the output. Also, you cannot declare variables in your for loop, except under certain conditions. I'm not sure how you got it to compile.
According this part:
int output = array[(int)(floor(0.9*count)) + 1];
int x = (floor(0.9*count) + 1);
while (array[x] == array[x + 1])
{
x = x + 1;
}
printf(" %d ", output);
In while you do not check if x has exceeded count... (What if all the top 10% numbers are equal?)
You set output in first line and print it in last, but do not do antything with it in meantime. (So all those lines in between do nothing).
You definitely are on the right track.
I was trying to solve the following problem:
Weighted Sum Problem
The closest problem I have done before is Kadane's algorithm, so I tried the "max ending here" approach, which led to the following DP-based program. The idea is to break the problem down into smaller identical problems (the usual DP).
#include<stdio.h>
#include<stdlib.h>
main(){
int i, n, m, C[20002], max, y, x, best, l, j;
int a[20002], b[20002];
scanf("%d %d", &n, &m);
for(i=0;i<n;i++){
scanf("%d",&C[i]);
}
a[0] = C[0];
max = C[0];
for(i=1;i<n;i++){
max = (C[i]>max) ? C[i] : max;
a[i] = max;
}
for(l=0;l<n;l++){
b[l] = 0;
}
for(y=2;y<m+1;y++){
for(x=y-1;x<n;x++){
best = max = 0;
for(j=0;j<y;j++){
max += (j+1) * C[j];
}
for(i=y-1;i<x+1;i++){
best = a[i-1] + y * C[i];
max = (best>max) ? best : max;
}
b[x] = max;
}
for(l=0;l<n;l++){
a[l] = b[l];
}
}
printf("%d\n",b[n-1]);
system("PAUSE");
return 0;
}
But this program does not work within the specified time limit (space limit is fine). Please give me a hint on the algorithm to be used on this problem.
EDIT.
Here is the explanation of the code:
Like in Kadane's, my idea is to look at a particular C[i], then take the maximum weighted sum for an m-subsequence ending at C[i], and finally take the max of all such values over all i. This will give us our answer. Now note that when you look at an m-subsequence ending at C[i], and take the maximum weighted sum, this is equivalent to taking the maximum weighted sum of an (m-1)-subsequence, contained in C[0] to C[i-1]. And this is a smaller problem which is identical to our original one. So we use recursion. To avoid double calling to functions, we make a table of values f[i][j], where f[i-i][j] is the answer to the problem which is identical to our problem with n replaced by i and m replaced by j. That is, we build a table of f[i][j], and our final answer is f[n-1][m] (that is, we use memoization). Now noting that only the previous column is required to compute an entry f[i][j], it is enough to keep only arrays. Those arrays are 'a' and 'b'.
Sorry for the long length, can't help it. :(
Try 0/1 Knapsack without repetition approach where at each step we decide whether to include an item or not.
Let MWS(i, j) represent the optimal maximum weighted sum of the sub-problem C[i...N] where i varies from 0 <= i <= N and 1 <= j <= M, and our goal is to find out the value of MWS(0, 1).
MWS(i, j) can be represented in the recursive ways as follow.
I am leaving the boundary conditions handling as an exercise for you.
Your general approach is correct. But there is a problem with your algorithm.
You could replace the body of the inner loop
best = max = 0;
for(j=0;j<y;j++){
max += (j+1) * C[j];
}
for(i=y-1;i<x+1;i++){
best = a[i-1] + y * C[i];
max = (best>max) ? best : max;
}
b[x] = max;
with
b[x] = MAX(b[x-1],a[x-1] + y * C[x]);
This will improve the time complexity of the algorithm. I.e. avoid recomputing b[i] for
all i < x. A common trait in dynamic programming.