Related
I got a task for hw to make a recursive function that checks between 2 unsigned long long numbers and check for common digits if there is its will print the common digits (its starts checking from right to left- when a match found we stop and print that digit)
if there is no same digits its will return -1
The problem is I could make it work for the first and last example but I am having trouble dealing with the second example.
any hints will be appreciated :)
```c
int findCommonDigit(unsigned long long n1, unsigned long long n2) {
int temp1 = 0, temp2 = 0;
if (n1 == 0 || n2 == 0)
return -1;
temp1 = n1 % 10;
temp2 = n2 % 10;
if (temp1 == temp2)
return temp1;
return findCommonDigit(n1 / 10, n2 / 10);
}
So, the task, as I understand it, is to determine whether or not two numbers share at least one digit. Constraints are:
Scan right to left.
In the case of (21, 12) return 1, not 2. (As per your commentary.)
The solution should be a recursive function.
Right-O. So, the trick is to compare every digit in the first number with every digit in the second number. There are quite a few ways to optimize this, but we will stick with an O(n²) brute-force method.
Given 123 and 456:
compare 3 with 6
compare 3 with 5
compare 3 with 4
compare 2 with 6
compare 2 with 5
compare 2 with 4
compare 1 with 6
compare 1 with 5
compare 1 with 4
Hopefully you can see that that was a nested loop:
for each digit in N1:
for each digit in N2:
match?
Conveniently, getting the rightmost (“least-significant”) digit value is a simple remainder operation:
int digit = number % 10;
After that we modify the number to shift all the digit places down one using integer division:
number = number / 10;
We want to use recursion (instead of a looping construct like while or for), so we need to transform each one of those loops into a recursive function call.
Basic Recursion
A recursive function works by having one or more termination conditions. Failing the termination condition, it just calls itself with updated arguments.
For simple example, we can take a counting loop:
void print_START_to_STOP( int start, int stop )
{
for (; start < stop; start = start+1)
printf( "%d\n", start );
}
And make it recursive:
void print_START_to_STOP( int start, int stop )
{
if (!(start < stop)) return; // termination condition
printf( "%d\n", start ); // (loop body)
print_START_to_STOP( start+1, stop ); // invoke next iteration
}
Take a few minutes to convince yourself that those two functions are equivalent. One uses an explicit loop. One uses recursion.
Inner Loop
Let’s start easy and work on a recursive function for the inner loop:
bool isDigitInNumber( int digit, unsigned long long number )
{
...
}
As recursion needs at least one termination condition, the first thing to check is if there are any digits left in number to check against the argument digit. If not, there is no match.
if (number == 0) return false;
The next thing to do is check to see if the least-significant digit of number matches the digit. If it does, we have another termination condition:
if ((number % 10) == digit) return true;
Otherwise we are left needing to check the remaining digits in number. This is where we invoke recursion:
return isDigitInNumber( digit, number/10 );
Zero?
You might ask, “What if digit is 0 and number has a 0 in it?”
Give it a try. Does it work for number == 201?
“Okay, so what if digit is 0 and number is also 0?”
That is a good question. Should findCommonDigit( 0, 0 ) return 0 or -1?
(Chances are your professor expects findCommonDigit( 0, 0 ) to return -1. I personally think it would be more correct if it returned 0. The only thing that shouldn’t return 0 is if either one of the numbers does not have an embedded zero, such as 123 and 456, and 0 and 123.)
Let’s come back to this in a minute.
Reflection
Let’s think about what we’ve done to simplify our problem:
isDigitInNumber( 3, 456 )
isDigitInNumber( 2, 456 )
isDigitInNumber( 1, 456 )
If any one of those is true, then we can return the matching digit. Otherwise we return -1.
You should also notice that there is still an outer loop to conquer.
Outer Loop
For the outer loop, we can create a new recursive function that makes use of the last recursive function.
Take a second and think about what this recursion is looping over: N1.
Just as the last function loops over N2 and gets the digit-to-compare by using remainder on N2, this recursive function loops over N1 and gets the digit-to-compare by using remainder on N1:
int digit_to_compare = n1 % 10;
Again we need some termination conditions and a recursion.
When do we stop and return -1?(After looping through all digits of N1 and not finding a match using isDigitInNumber().)So... when N1 is zero we are done. No match. Return -1.
if (n1 == 0) return -1;
Otherwise we need to try to match the digit-to-compare with all the digits in N2:
if (isDigitInNumber( digit_to_compare, n2 )) return digit_to_compare;
And finally, the digit wasn’t matched, we need to recurse on the next digit in N1:
return findCommonDigit( ... );
You are basically done.
Zero Redux
Now back to that tricky question about zeros.
Remember that the inner-loop algorithm could not check for the possibility of zero matching zero. But that’s okay. It wasn’t the right place to check.
The right place is before you do any loops at all. Right at the beginning of your algorithm, check to see if N1 == N2. If it does, then the rightmost digit of both numbers is the same. Even if both numbers are zero.
int findCommonDigit( ... )
{
if (n1 == n2) return (n1 % 10); // return the matching digit, which might be 0
return findCommonDigit_Impl( n1, n2 );
}
You will have had to rename the last findCommonDigit() function to findCommonDigit_Impl(), of course.
So many functions! What the double-hockeysticks?!
In order to handle the special condition of zeros we had to add yet another function to the mix.
That is kind of unavoidable. Otherwise we can’t tell the difference between findCommonDigit( 123, 0 ) and findCommonDigit( 0, 0 ), and the result differs between ( 123, 0 ) and ( 0, 123 ).
Anyway, we now have have three functions:
bool isDigitInNumber( int digit, unsigned long long number );
int findCommonDigit_Impl( unsigned long long n1, unsigned long long n2 );
int findCommonDigit( unsigned long long n1, unsigned long long n2 );
The last one is the one that gets invoked by the user:
int main(void)
{
printf( "%d\n", findCommonDigit( 1234, 2 ) );
The other two are the recursive functions, and do not get invoked by the user.
It is entirely possible to combine these all into a single recursive function.
Don’t waste your time though. Doing that increases complexity, and you would have to add additional formal arguments to deal with it. (Or use global variables or some other Don’t-Do-That-Crufty hack.)
It is entirely okay to have useful helper functions. And when dealing with recursion, this kind of multiple-function structure is actually very common and normal.
Hopefully this wasn’t too long-winded, nor gave away the answer too easily. Much of the time spent here was to help think your way through designing a recursive algorithm, so that when you have to do it again in the future you won’t be utterly lost. (Recursion is hard!)
AAAANNNND, hopefully your classmates will get it too, but without producing an exact copy of you code, lol. Professors want you to learn, not cheat off the internet, and I’ve made this fairly easy to draw that kind of conclusion, alas.
P.S
BTW, you might get away with using a loop inside your recursive function: an explicit inner loop for the digits of N2 and recursion for the outer loop over N1. IDK if that is acceptable. This answer assumes no loops allowed.
You can use a loop based function instead like following:
int findCommonDigit(unsigned long long n1, unsigned long long n2) {
int digitN1[11] = {0}, digitN2[11] = {0};
while(n1) {
int x = n1 % 10;
n1 /= 10;
digitN1[x] = 1;
}
while(n2) {
int x = n2 % 10;
n2 /= 10;
digitN2[x] = 1;
}
for(int i=0; i<10; i++) {
if(digitN1[i] && digitN2[i]) {
return i;
}
}
return -1;
}
Here digitN1 and digitN2 are two flag arrays used to store whether digits[0..9] are set on numbers n1 and n2 respectively. Then we use a for loop to check whether any digit is on both numbers or not. If no common digits found, -1 is returned.
You can write a while loop until "n2 > 0" in main function. For every digit you will call "findCommonDigit" function and check is the return value is -1 or not. If you get a digit that is not -1 then print it and break the While loop. After the while loop you can write printf("-1").
For that you have to change this return findCommonDigit(n1 / 10, n2 / 10); to this return findCommonDigit(n1 / 10, n2);
Otherwise you can change your function to this,
int findCommonDigit(unsigned long long n1, unsigned long long n2) {
int temp1 = 0, temp2 = 0;
if (n1 == 0 || n2 == 0){
return -1;
}
temp1 = n1 % 10;
temp2 = n2 % 10;
if (temp1 == temp2){
return temp1;
}
n1 /= 10;
return findCommonDigit(n1, n2);
n2 /= 10;
return findCommonDigit(n1, n2);
}
This is what I came up with based on your and my test cases.
Twice the recursion twice the fun!
#include <stdio.h>
#define DEBUG_FUNCTION 0
int compareN1Digits(unsigned long long n1, unsigned long long n2)
{
int n1RightDigit = n1 % 10;
if(DEBUG_FUNCTION) printf(" n1 right most digit : %d\n", n1RightDigit);
int result = -1;
if (n1RightDigit != n2)
{
if(DEBUG_FUNCTION) printf("Not a match.\n");
if (n1 > 10)
{
result = compareN1Digits(n1 / 10, n2);
}
}
else
{
result = n1RightDigit;
}
return result;
}
int findCommonDigit(unsigned long long n1, unsigned long long n2)
{
int n2RightDigit = n2 % 10;
if(DEBUG_FUNCTION) printf("n2 right most digit : %d\n", n2RightDigit);
int result = -1;
result = compareN1Digits(n1, n2 % 10);
if (result == -1)
{
if (n2 >= 10)
{
result = findCommonDigit(n1, n2 / 10);
}
}
return result;
}
void RunTestCase(unsigned long long n1, unsigned long long n2, int expectedResult)
{
int result;
result = findCommonDigit(n1, n2);
if (result == expectedResult)
{
printf("Corrent Result\n\n");
}
else
{
printf("Result NOT corrent!\n\n");
}
}
int main()
{
// Test Case 1
// 22222446, 113355578889 => function will give back -1
RunTestCase(22222446, 113355578889, -1);
// Test Case 2
// 13259438, 2 => function will give back 2
RunTestCase(13259438, 2, 2);
// Test Case 3
// 112233445, 112233445 => function will give back 5.
RunTestCase(112233445, 112233445, 5);
// Test Case 4
// 2, 13259438 => function will give back 2
RunTestCase(2, 13259438, 2);
// Test Case 5
// 12034, 567809 => function will give back 0
RunTestCase(12034, 567809, 0);
// Test Case 6
// 1, 1 => function will give back 1
RunTestCase(1, 1, 1);
// Test Case 7
// 0, 0 => function will give back 0
RunTestCase(0, 0, 0);
return 0;
}
just a fibonacci algorithm, how do i print every number of fibonacci sequence without repeat every step?
Does recursive functions is a good use in any way? I know it is more legible, but there is a visible delay in this simple algorithm if i put n = 40, whereas the iterative way of doing it is instantaneous.
int fib(int n)
{
if (n == 0)
{
return 0;
}
else if (n == 1)
{
return 1;
}
return fib(n - 1) + fib(n - 2);
}
You can easily optimize the recursive solution by memoizing the already-computed values:
int fib(int n) {
static int cache[48] = {0}; // should be enough to hold all int fibs
if(n < 2) return n; // initial conditions
else if(cache[n]) return cache[n]; // a value already computed and memoized
else return cache[n] = fib(n - 1) + fib(n - 2); // the largest so far
}
Should speed up the computation by, uh, some factor.
Imperative languages like C do not always map well to functional definitions of algorithms.
Non-recursive is generally faster because both the compiler and processor can more easily optimize/parallel'ize the execution and you're not wasting energy, needlessly pushing and popping the stack. Either way, all you need are the previous two fib values to calculate the next one:
void PrintNFibs(unsigned n)
{
size_t a = 1;
size_t b = 1;
size_t sum;
printf("0\n1\n1\n");
while ( n-- )
{
sum = a + b;
printf("%zu\n", sum);
a = b;
b = sum;
}
}
It's one thing to define an algorithm in terms of itself (recursion) and another to implement it efficiently in C. For something as simple as Fibonacci however, I would not use recursion, but here's one anyway:
void PrintNFibsR(unsigned n)
{
static size_t a = 0;
static size_t b = 1;
static size_t sum;
sum = a + b;
if ( a == 0 )
{
printf("0\n1\n");
}
printf("%zu\n", sum);
if ( n > 1 )
{
a = b;
b = sum;
PrintNFibsR(n - 1);
}
}
Notice that all we're really doing here is passing the loop counter. Wasteful but technically recursive, if not actually functional. The problem with writing C code that looks just like the recursive Fibonacci algorithm definition, is it burns energy and stack space for no good reason. The only way you can print the values in the correct order without calculating and storing each one of them in advance, is to alter the algorithm.
I am working on a project that requires me to find largest n such that x^n<=y where x and y are provided. I am using the gmp library and working with huge numbers in c.
Constraints:
x>=1 &
y>=1
Using the first approach that came into my mind, it took me around 5 secs to find n when x=12 and y = 411^20000 i.e,
int n=0;
int x=12;
int y=100;
int temp;
int answer;
while(1)
{
temp = pow(x,n);
if(temp>y)
{
answer = n-1;
return(0);
}
n++;
}
Note: Not actual code. Didn't want to complicate things with gmp syntax
Is there a faster algorithm?
Entire code:
https://pastebin.com/J1vbmEbK
If gmp library contains logarithm function, use it
result = Floor(log(y)/log(x))
Otherwise you can exploit binary search - square x (x, x^2, x^4, x^8) while possible, then diminish power step
Quick and dirty implementation for checking with usual numbers
returns 24 for x = 2; y = 31415926.0;
(same as Floor(ln(y)/ln(x))
int FindXPower(double x, double y)
{
int Powers[64];
double t, s, next;
int ix;
//exponential search phase
ix = 0;
t = x;
while (t <= y)
{
Powers[ix++] = t; //remember them to use later
t = t * t;
};
//now powers contain [x,x^2,x^4,x^8,x^16...]
ix--;
int Result = 1 << ix; // 2^lastindex: 1,2,4,8,16,32...
//binary search phase
s = Powers[ix--]; //max value after squaring
while ((s < y) && (ix >= 0))
{
t = Powers[ix];
next = s * t;
while (next < y)
{
s = next;
next = next * t;
Result = Result + (1<<ix);
}
ix--;
};
return Result;
}
Instead of linearly decreasing n you could search for the correct value by dichotomy.
Define two variables: n_low and n_high with the invariant that at any moment in time x^n_high is strictly greater than y and x^n_low is less than or equal to y.
At each iteration, compute the value of m which halves the distance between n_high and n_low.
Then compare x^m with y. If it is strictly greated, then assign: n_high = m else assign n_low = m. When n_low+1==n_high the value of n_low is the value you're looking for.
I assume you're working with arbitrary-precision integers (GMP also supports arbitrary-precision floating point).
Convert the bigints to floating-point. This will incur rounding errors.
Estimate the result computing n_est = floor(log(y_float) / log(x_float)).
The actual n is either n_est - 1, n_est, or n_est + 1 which can be checked easily.
This question already has answers here:
nth fibonacci number in sublinear time
(16 answers)
Closed 6 years ago.
I am a CSE student and preparing myself for programming contest.Now I am working on Fibonacci series. I have a input file of size about some Kilo bytes containing positive integers. Input formate looks like
3 5 6 7 8 0
A zero means the end of file. Output should like
2
5
8
13
21
my code is
#include<stdio.h>
int fibonacci(int n) {
if (n==1 || n==2)
return 1;
else
return fibonacci(n-1) +fibonacci(n-2);
}
int main() {
int z;
FILE * fp;
fp = fopen ("input.txt","r");
while(fscanf(fp,"%d", &z) && z)
printf("%d \n",fibonacci(z));
return 0;
}
The code works fine for sample input and provide accurate result but problem is for my real input set it is taking more time than my time limit. Can anyone help me out.
You could simply use a tail recursion version of a function that returns the two last fibonacci numbers if you have a limit on the memory.
int fib(int n)
{
int a = 0;
int b = 1;
while (n-- > 1) {
int t = a;
a = b;
b += t;
}
return b;
}
This is O(n) and needs a constant space.
You should probably look into memoization.
http://en.wikipedia.org/wiki/Memoization
It has an explanation and a fib example right there
You can do this by matrix multiplictation, raising the matrix to power n and then multiply it by an vector. You can raise it to power in logaritmic time.
I think you can find the problem here. It's in romanian but you can translate it with google translate. It's exactly what you want, and the solution it's listed there.
Your algorithm is recursive, and approximately has O(2^N) complexity.
This issue has been discussed on stackoverflow before:
Computational complexity of Fibonacci Sequence
There is also a faster implementation posted in that particular discussion.
Look in Wikipedia, there is a formula that gives the number in the Fibonacci sequence with no recursion at all
Use memoization. That is, you cache the answers to avoid unnecessary recursive calls.
Here's a code example:
#include <stdio.h>
int memo[10000]; // adjust to however big you need, but the result must fit in an int
// and keep in mind that fibonacci values grow rapidly :)
int fibonacci(int n) {
if (memo[n] != -1)
return memo[n];
if (n==1 || n==2)
return 1;
else
return memo[n] = fibonacci(n-1) +fibonacci(n-2);
}
int main() {
for(int i = 0; i < 10000; ++i)
memo[i] = -1;
fibonacci(50);
}
Nobody mentioned the 2 value stack array version, so I'll just do it for completeness.
// do not call with i == 0
uint64_t Fibonacci(uint64_t i)
{
// we'll only use two values on stack,
// initialized with F(1) and F(2)
uint64_t a[2] = {1, 1};
// We do not enter loop if initial i was 1 or 2
while (i-- > 2)
// A bitwise AND allows switching the storing of the new value
// from index 0 to index 1.
a[i & 1] = a[0] + a[1];
// since the last value of i was 0 (decrementing i),
// the return value is always in a[0 & 1] => a[0].
return a[0];
}
This is a O(n) constant stack space solution that will perform slightly the same than memoization when compiled with optimization.
// Calc of fibonacci f(99), gcc -O2
Benchmark Time(ns) CPU(ns) Iterations
BM_2stack/99 2 2 416666667
BM_memoization/99 2 2 318181818
The BM_memoization used here will initialize the array only once and reuse it for every other call.
The 2 value stack array version performs identically as a version with a temporary variable when optimized.
You can also use the fast doubling method of generating Fibonacci series
Link: fastest-way-to-compute-fibonacci-number
It is actually derived from the results of the matrix exponentiation method.
Use the golden-ratio
Build an array Answer[100] in which you cache the results of fibonacci(n).
Check in your fibonacci code to see if you have precomputed the answer, and
use that result. The results will astonish you.
Are you guaranteed that, as in your example, the input will be given to you in ascending order? If so, you don't even need memoization; just keep track of the last two results, start generating the sequence but only display the Nth number in the sequence if N is the next index in your input. Stop when you hit index 0.
Something like this:
int i = 0;
while ( true ) {
i++; //increment index
fib_at_i = generate_next_fib()
while ( next_input_index() == i ) {
println fib_at_i
}
I leave exit conditions and actually generating the sequence to you.
In C#:
static int fib(int n)
{
if (n < 2) return n;
if (n == 2) return 1;
int k = n / 2;
int a = fib(k + 1);
int b = fib(k);
if (n % 2 == 1)
return a * a + b * b;
else
return b * (2 * a - b);
}
Matrix multiplication, no float arithmetic, O(log N) time complexity assuming integer multiplication/addition is done in constant time.
Here goes python code
def fib(n):
x,y = 1,1
mat = [1,1,1,0]
n -= 1
while n>0:
if n&1==1:
x,y = x*mat[0]+y*mat[1], x*mat[2]+y*mat[3]
n >>= 1
mat[0], mat[1], mat[2], mat[3] = mat[0]*mat[0]+mat[1]*mat[2], mat[0]*mat[1]+mat[1]*mat[3], mat[0]*mat[2]+mat[2]*mat[3], mat[1]*mat[2]+mat[3]*mat[3]
return x
You can reduce the overhead of the if statement: Calculating Fibonacci Numbers Recursively in C
First of all, you can use memoization or an iterative implementation of the same algorithm.
Consider the number of recursive calls your algorithm makes:
fibonacci(n) calls fibonacci(n-1) and fibonacci(n-2)
fibonacci(n-1) calls fibonacci(n-2) and fibonacci(n-3)
fibonacci(n-2) calls fibonacci(n-3) and fibonacci(n-4)
Notice a pattern? You are computing the same function a lot more times than needed.
An iterative implementation would use an array:
int fibonacci(int n) {
int arr[maxSize + 1];
arr[1] = arr[2] = 1; // ideally you would use 0-indexing, but I'm just trying to get a point across
for ( int i = 3; i <= n; ++i )
arr[i] = arr[i - 1] + arr[i - 2];
return arr[n];
}
This is already much faster than your approach. You can do it faster on the same principle by only building the array once up until the maximum value of n, then just print the correct number in a single operation by printing an element of your array. This way you don't call the function for every query.
If you can't afford the initial precomputation time (but this usually only happens if you're asked for the result modulo something, otherwise they probably don't expect you to implement big number arithmetic and precomputation is the best solution), read the fibonacci wiki page for other methods. Focus on the matrix approach, that one is very good to know in a contest.
#include<stdio.h>
int g(int n,int x,int y)
{
return n==0 ? x : g(n-1,y,x+y);}
int f(int n)
{
return g(n,0,1);}
int main (void)
{
int i;
for(i=1; i<=10 ; i++)
printf("%d\n",f(i)
return 0;
}
In the functional programming there is a special algorithm for counting fibonacci. The algorithm uses accumulative recursion. Accumulative recursion are used to minimize the stack size used by algorithms. I think it will help you to minimize the time. You can try it if you want.
int ackFib (int n, int m, int count){
if (count == 0)
return m;
else
return ackFib(n+m, n, count-1);
}
int fib(int n)
{
return ackFib (0, 1, n+1);
}
use any of these: Two Examples of recursion, One with for Loop O(n) time and one with golden ratio O(1) time:
private static long fibonacciWithLoop(int input) {
long prev = 0, curr = 1, next = 0;
for(int i = 1; i < input; i++){
next = curr + prev;
prev = curr;
curr = next;
}
return curr;
}
public static long fibonacciGoldenRatio(int input) {
double termA = Math.pow(((1 + Math.sqrt(5))/2), input);
double termB = Math.pow(((1 - Math.sqrt(5))/2), input);
double factor = 1/Math.sqrt(5);
return Math.round(factor * (termA - termB));
}
public static long fibonacciRecursive(int input) {
if (input <= 1) return input;
return fibonacciRecursive(input - 1) + fibonacciRecursive(input - 2);
}
public static long fibonacciRecursiveImproved(int input) {
if (input == 0) return 0;
if (input == 1) return 1;
if (input == 2) return 1;
if (input >= 93) throw new RuntimeException("Input out of bounds");
// n is odd
if (input % 2 != 0) {
long a = fibonacciRecursiveImproved((input+1)/2);
long b = fibonacciRecursiveImproved((input-1)/2);
return a*a + b*b;
}
// n is even
long a = fibonacciRecursiveImproved(input/2 + 1);
long b = fibonacciRecursiveImproved(input/2 - 1);
return a*a - b*b;
}
using namespace std;
void mult(LL A[ 3 ][ 3 ], LL B[ 3 ][ 3 ]) {
int i,
j,
z;
LL C[ 3 ][ 3 ];
memset(C, 0, sizeof( C ));
for(i = 1; i <= N; i++)
for(j = 1; j <= N; j++) {
for(z = 1; z <= N; z++)
C[ i ][ j ] = (C[ i ][ j ] + A[ i ][ z ] * B[ z ][ j ] % mod ) % mod;
}
memcpy(A, C, sizeof(C));
};
void readAndsolve() {
int i;
LL k;
ifstream I(FIN);
ofstream O(FOUT);
I>>k;
LL A[3][3];
LL B[3][3];
A[1][1] = 1; A[1][2] = 0;
A[2][1] = 0; A[2][2] = 1;
B[1][1] = 0; B[1][2] = 1;
B[2][1] = 1; B[2][2] = 1;
for(i = 0; ((1<<i) <= k); i++) {
if( k & (1<<i) ) mult(A, B);
mult(B, B);
}
O<<A[2][1];
}
//1,1,2,3,5,8,13,21,33,...
int main() {
readAndsolve();
return(0);
}
public static int GetNthFibonacci(int n)
{
var previous = -1;
var current = 1;
int element = 0;
while (1 <= n--)
{
element = previous + current;
previous = current;
current = element;
}
return element;
}
This is similar to answers given before, but with some modifications. Memorization, as stated in other answers, is another way to do this, but I dislike code that doesn't scale as technology changes (size of an unsigned int varies depending on the platform) so the highest value in the sequence that can be reached may also vary, and memorization is ugly in my opinion.
#include <iostream>
using namespace std;
void fibonacci(unsigned int count) {
unsigned int x=0,y=1,z=0;
while(count--!=0) {
cout << x << endl; // you can put x in an array or whatever
z = x;
x = y;
y += z;
}
}
int main() {
fibonacci(48);// 48 values in the sequence is the maximum for a 32-bit unsigend int
return 0;
}
Additionally, if you use <limits> its possible to write a compile-time constant expression that would give you the largest index within the sequence that can be reached for any integral data type.
#include<stdio.h>
main()
{
int a,b=2,c=5,d;
printf("%d %d ");
do
{
d=b+c;
b=c;
c=d;
rintf("%d ");
}
I recently came across a question somewhere:
Suppose you have an array of 1001 integers. The integers are in random order, but you know each of the integers is between 1 and 1000 (inclusive). In addition, each number appears only once in the array, except for one number, which occurs twice. Assume that you can access each element of the array only once. Describe an algorithm to find the repeated number. If you used auxiliary storage in your algorithm, can you find an algorithm that does not require it?
What I am interested in to know is the second part, i.e., without using auxiliary storage. Do you have any idea?
Just add them all up, and subtract the total you would expect if only 1001 numbers were used from that.
Eg:
Input: 1,2,3,2,4 => 12
Expected: 1,2,3,4 => 10
Input - Expected => 2
Update 2: Some people think that using XOR to find the duplicate number is a hack or trick. To which my official response is: "I am not looking for a duplicate number, I am looking for a duplicate pattern in an array of bit sets. And XOR is definitely suited better than ADD to manipulate bit sets". :-)
Update: Just for fun before I go to bed, here's "one-line" alternative solution that requires zero additional storage (not even a loop counter), touches each array element only once, is non-destructive and does not scale at all :-)
printf("Answer : %d\n",
array[0] ^
array[1] ^
array[2] ^
// continue typing...
array[999] ^
array[1000] ^
1 ^
2 ^
// continue typing...
999^
1000
);
Note that the compiler will actually calculate the second half of that expression at compile time, so the "algorithm" will execute in exactly 1002 operations.
And if the array element values are know at compile time as well, the compiler will optimize the whole statement to a constant. :-)
Original solution: Which does not meet the strict requirements of the questions, even though it works to find the correct answer. It uses one additional integer to keep the loop counter, and it accesses each array element three times - twice to read it and write it at the current iteration and once to read it for the next iteration.
Well, you need at least one additional variable (or a CPU register) to store the index of the current element as you go through the array.
Aside from that one though, here's a destructive algorithm that can safely scale for any N up to MAX_INT.
for (int i = 1; i < 1001; i++)
{
array[i] = array[i] ^ array[i-1] ^ i;
}
printf("Answer : %d\n", array[1000]);
I will leave the exercise of figuring out why this works to you, with a simple hint :-):
a ^ a = 0
0 ^ a = a
A non destructive version of solution by Franci Penov.
This can be done by making use of the XOR operator.
Lets say we have an array of size 5: 4, 3, 1, 2, 2
Which are at the index: 0, 1, 2, 3, 4
Now do an XOR of all the elements and all the indices. We get 2, which is the duplicate element. This happens because, 0 plays no role in the XORing. The remaining n-1 indices pair with same n-1 elements in the array and the only unpaired element in the array will be the duplicate.
int i;
int dupe = 0;
for(i = 0; i < N; i++) {
dupe = dupe ^ arr[i] ^ i;
}
// dupe has the duplicate.
The best feature of this solution is that it does not suffer from overflow problems that is seen in the addition based solution.
Since this is an interview question, it would be best to start with the addition based solution, identify the overflow limitation and then give the XOR based solution :)
This makes use of an additional variable so does not meet the requirements in the question completely.
Add all the numbers together. The final sum will be the 1+2+...+1000+duplicate number.
To paraphrase Francis Penov's solution.
The (usual) problem is: given an array of integers of arbitrary length that contain only elements repeated an even times of times except for one value which is repeated an odd times of times, find out this value.
The solution is:
acc = 0
for i in array: acc = acc ^ i
Your current problem is an adaptation. The trick is that you are to find the element that is repeated twice so you need to adapt solution to compensate for this quirk.
acc = 0
for i in len(array): acc = acc ^ i ^ array[i]
Which is what Francis' solution does in the end, although it destroys the whole array (by the way, it could only destroy the first or last element...)
But since you need extra-storage for the index, I think you'll be forgiven if you also use an extra integer... The restriction is most probably because they want to prevent you from using an array.
It would have been phrased more accurately if they had required O(1) space (1000 can be seen as N since it's arbitrary here).
Add all numbers. The sum of integers 1..1000 is (1000*1001)/2. The difference from what you get is your number.
One line solution in Python
arr = [1,3,2,4,2]
print reduce(lambda acc, (i, x): acc ^ i ^ x, enumerate(arr), 0)
# -> 2
Explanation on why it works is in #Matthieu M.'s answer.
If you know that we have the exact numbers 1-1000, you can add up the results and subtract 500500 (sum(1, 1000)) from the total. This will give the repeated number because sum(array) = sum(1, 1000) + repeated number.
Well, there is a very simple way to do this... each of the numbers between 1 and 1000 occurs exactly once except for the number that is repeated.... so, the sum from 1....1000 is 500500. So, the algorithm is:
sum = 0
for each element of the array:
sum += that element of the array
number_that_occurred_twice = sum - 500500
n = 1000
s = sum(GivenList)
r = str(n/2)
duplicate = int( r + r ) - s
public static void main(String[] args) {
int start = 1;
int end = 10;
int arr[] = {1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10};
System.out.println(findDuplicate(arr, start, end));
}
static int findDuplicate(int arr[], int start, int end) {
int sumAll = 0;
for(int i = start; i <= end; i++) {
sumAll += i;
}
System.out.println(sumAll);
int sumArrElem = 0;
for(int e : arr) {
sumArrElem += e;
}
System.out.println(sumArrElem);
return sumArrElem - sumAll;
}
No extra storage requirement (apart from loop variable).
int length = (sizeof array) / (sizeof array[0]);
for(int i = 1; i < length; i++) {
array[0] += array[i];
}
printf(
"Answer : %d\n",
( array[0] - (length * (length + 1)) / 2 )
);
Do arguments and callstacks count as auxiliary storage?
int sumRemaining(int* remaining, int count) {
if (!count) {
return 0;
}
return remaining[0] + sumRemaining(remaining + 1, count - 1);
}
printf("duplicate is %d", sumRemaining(array, 1001) - 500500);
Edit: tail call version
int sumRemaining(int* remaining, int count, int sumSoFar) {
if (!count) {
return sumSoFar;
}
return sumRemaining(remaining + 1, count - 1, sumSoFar + remaining[0]);
}
printf("duplicate is %d", sumRemaining(array, 1001, 0) - 500500);
public int duplicateNumber(int[] A) {
int count = 0;
for(int k = 0; k < A.Length; k++)
count += A[k];
return count - (A.Length * (A.Length - 1) >> 1);
}
A triangle number T(n) is the sum of the n natural numbers from 1 to n. It can be represented as n(n+1)/2. Thus, knowing that among given 1001 natural numbers, one and only one number is duplicated, you can easily sum all given numbers and subtract T(1000). The result will contain this duplicate.
For a triangular number T(n), if n is any power of 10, there is also beautiful method finding this T(n), based on base-10 representation:
n = 1000
s = sum(GivenList)
r = str(n/2)
duplicate = int( r + r ) - s
I support the addition of all the elements and then subtracting from it the sum of all the indices but this won't work if the number of elements is very large. I.e. It will cause an integer overflow! So I have devised this algorithm which may be will reduce the chances of an integer overflow to a large extent.
for i=0 to n-1
begin:
diff = a[i]-i;
dup = dup + diff;
end
// where dup is the duplicate element..
But by this method I won't be able to find out the index at which the duplicate element is present!
For that I need to traverse the array another time which is not desirable.
Improvement of Fraci's answer based on the property of XORing consecutive values:
int result = xor_sum(N);
for (i = 0; i < N+1; i++)
{
result = result ^ array[i];
}
Where:
// Compute (((1 xor 2) xor 3) .. xor value)
int xor_sum(int value)
{
int modulo = x % 4;
if (modulo == 0)
return value;
else if (modulo == 1)
return 1;
else if (modulo == 2)
return i + 1;
else
return 0;
}
Or in pseudocode/math lang f(n) defined as (optimized):
if n mod 4 = 0 then X = n
if n mod 4 = 1 then X = 1
if n mod 4 = 2 then X = n+1
if n mod 4 = 3 then X = 0
And in canonical form f(n) is:
f(0) = 0
f(n) = f(n-1) xor n
My answer to question 2:
Find the sum and product of numbers from 1 -(to) N, say SUM, PROD.
Find the sum and product of Numbers from 1 - N- x -y, (assume x, y missing), say mySum, myProd,
Thus:
SUM = mySum + x + y;
PROD = myProd* x*y;
Thus:
x*y = PROD/myProd; x+y = SUM - mySum;
We can find x,y if solve this equation.
In the aux version, you first set all the values to -1 and as you iterate check if you have already inserted the value to the aux array. If not (value must be -1 then), insert. If you have a duplicate, here is your solution!
In the one without aux, you retrieve an element from the list and check if the rest of the list contains that value. If it contains, here you've found it.
private static int findDuplicated(int[] array) {
if (array == null || array.length < 2) {
System.out.println("invalid");
return -1;
}
int[] checker = new int[array.length];
Arrays.fill(checker, -1);
for (int i = 0; i < array.length; i++) {
int value = array[i];
int checked = checker[value];
if (checked == -1) {
checker[value] = value;
} else {
return value;
}
}
return -1;
}
private static int findDuplicatedWithoutAux(int[] array) {
if (array == null || array.length < 2) {
System.out.println("invalid");
return -1;
}
for (int i = 0; i < array.length; i++) {
int value = array[i];
for (int j = i + 1; j < array.length; j++) {
int toCompare = array[j];
if (value == toCompare) {
return array[i];
}
}
}
return -1;
}