Running time of GCD Algorithm? - algorithm

unsigned int gcd(unsigned int n, unsigned int m)
{
if (n == 0)
return m;
if (m == 0)
return n;
while (m! = n)
{
if (n > m)
n = n − m;
else
m = m − n;
}
return n;
}
Some psuedocode for an iterative GCD algorithm using a while loop. I there are no places where there is anything being divided by 2, so I do not think that it is logarithmic. Since the while loop runs for a time directly proportional to N does it make it linear like O(N)?

I would say it is O(max(n,m)) because it big-O should be symmetric for n vs m since the algorithm is.
#PaulHankin improves this to be O(max(n,m)/gcd(n,m)).

Related

Count integer partions with k parts, each below some threshold m

I want to count the number of ways we can partition the number n, into k distinct parts where each part is not larger than m.
For k := 2 i have following algorithm:
public int calcIntegerPartition(int n, int k, int m) {
int cnt=0;
for(int i=1; i <= m;i++){
for(int j=i+1; j <= m; j++){
if(i+j == n){
cnt++;
break;
}
}
}
return cnt;
}
But how can i count integer partitions with k > 2? Usually I have n > 100000, k := 40, m < 10000.
Thank you in advance.
Let's start by choosing the k largest legal numbers: m, m-1, m-2, ..., m-(k-1). This adds up to k*m - k(k-1)/2. If m < k, there are no solutions because the smallest partition would be <= 0. Let's assume m >= k.
Let's say p = (km - k(k-1)/2) - n.
If p < 0, there are no solutions because the largest number we can make is less than n. Let's assume p >= 0. Note that if p = 0 there is exactly one solution, so let's assume p > 0.
Now, imagine we start by choosing the k largest distinct legal integers, and we then correct this to get a solution. Our correction involves moving values to the left (on the number line) 1 slot, into empty slots, exactly p times. How many ways can we do this?
The smallest value to start with is m-(k-1), and it can move as far down as 1, so up to m-k times. After this, each successive value can move up to its predecessor's move.
Now the problem is, how many nonincreasing integer sequences with a max value of m-k sum to p? This is the partition problem. I.e., how many ways can we partition p (into at most k partitions). This is no closed-form solution to this.
Someone has already written up a nice answer of this problem here (which will need slight modification to meet your restrictions):
Is there an efficient algorithm for integer partitioning with restricted number of parts?
As #Dave alludes to, there is already a really nice answer to the simple restricted integer case (found here (same link as #Dave): Is there an efficient algorithm for integer partitioning with restricted number of parts?).
Below is a variant in C++ which takes into account the maximum value of each restricted part. First, here is the workhorse:
#include <vector>
#include <algorithm>
#include <iostream>
int width;
int blockSize;
static std::vector<double> memoize;
double pStdCap(int n, int m, int myMax) {
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
if (m < 2) return m;
const int block = myMax * blockSize + (n - m) * width + m - 2;
if (memoize[block]) return memoize[block];
int niter = n / m;
if (m == 2) {
if (myMax * 2 >= n) {
myMax = std::min(myMax, n - 1);
return niter - (n - 1 - myMax);
} else {
return 0;
}
}
double count = 0;
for (; niter--; n -= m, --myMax) {
count += (memoize[myMax * blockSize + (n - m) * width + m - 3] = pStdCap(n - 1, m - 1, myMax));
}
return count;
}
As you can see pStdCap is very similar to the linked solution. The one noticeable difference are the 2 additional checks at the top:
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
And here is the function that sets up the recursion:
double CountPartLenCap(int n, int m, int myMax) {
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
if (m < 2) return m;
if (m == 2) {
if (myMax * 2 >= n) {
myMax = std::min(myMax, n - 1);
return n / m - (n - 1 - myMax);
} else {
return 0;
}
}
width = m;
blockSize = m * (n - m + 1);
memoize = std::vector<double>((myMax + 1) * blockSize, 0.0);
return pStdCap(n, m, myMax);
}
Explanation of the parameters:
n is the integer that you are partitioning
m is the length of each partition
myMax is the maximum value that can appear in a given partition. (the OP refers to this as the threshold)
Here is a live demonstration https://ideone.com/c3WohV
And here is a non memoized version of pStdCap which is a bit easier to understand. This is originally found in this answer to Is there an efficient way to generate N random integers in a range that have a given sum or average?
int pNonMemoStdCap(int n, int m, int myMax) {
if (myMax * m < n) return 0;
if (myMax * m == n) return 1;
if (m < 2) return m;
if (n < m) return 0;
if (n <= m + 1) return 1;
int niter = n / m;
int count = 0;
for (; niter--; n -= m, --myMax) {
count += pNonMemoStdCap(n - 1, m - 1, myMax);
}
return count;
}
If you actually intend to calculate the number of partitions for numbers as large as 10000, you are going to need a big int library as CountPartLenCap(10000, 40, 300) > 3.2e37 (Based off the OP's requirement).

Big O notations - Recursive functions

I need to find the complexity of this recursive algorithms, so, i have 3 recursive algorithms and simply just want to know the Big O Notation for them. I think i have the solution for 2 of these algorithms, just wanna check with the community.
int f1(int n)
{
if ( n<= 1)
return (1);
else
return (n *f1(n-1))
}
I think the solution of this is O(n).
int f2 (int n)
{
if(n<=1)
return(1);
else
return(n*f2(n / 2))
}
I think the solution of this is O(Log 2 (n))
int f3
{
int x, i;
if( n <= 1)
return 1;
else
{
x = f3 (n / 2);
for( i = 1 ; i <= n ; i++)
x++;
return x;
}
}
What is the complexity of this recursive algorithm, i don't have the solution for this algorithm, Can you help me?
Your first two answer is correct.
Let's do analysis for your third problem,
for each times, n is divides by 2 and we need to add x for n times,
so the complexity will be
1*n+1*n/2+1*n/4+.....+1=n(1+1/2+1/4+...)=O(n)
#codecrazers answer already covers up how to calculate the complexity step-by-step. But in general the Master-Theorem makes the problem a lot simpler.
To start, lets transform this code
int f3 (int n)
{
int x, i;
if( n <= 1)
return 1;
else
{
x = f3 (n / 2);
for( i = 1 ; i <= n ; i++)
x++;
return x;
}
}
Into a recurrence:
int f(int n)
{
if( n <= 1)
1
else
f(n / 2) + θ(n)
}
So
T(n) = T(n / 2) + θ(n)
T(n <= 1) = 1
Which is case 3, thus yielding
T(n) = θ(n)

How to calculate complexity of an algorithm?

I've trying to calculate complexity of an algorithm, but I'm not sure how to do that. I know how to solve simple algorithms, but I'm struggling with recursion.
There is the code of recursion:
static int F(int m, int n)
{
if (n == 0)
return m;
if (m == 0 && n > 0)
return n;
else
return Math.Min((1 + F(m - 1, n)), Math.Min((1 + F(m, n - 1)), (D(m - 1, n - 1) + F(m - 1, n - 1))));
}
Can someone explain me or help me to calculate this function? I've tried googling it but I can find only simple examples.(maybe mine code is also simple?)
Thank you!
I don't know what the D function is in your first piece of code. I'll consider it as a constant function.
The first piece of your code is equivalent to the following one.
static int F(int m, int n)
{
if (n == 0 || m == 0)
return n + m;
else
return Math.Min((1 + F(m - 1, n)), Math.Min((1 + F(m, n - 1)), (D(m - 1, n - 1) + F(m - 1, n - 1))));
}
It's a little difficult to calculate the time complexity of a recursive function with two parameters, but we can estimate it roughly. We have the following equation.
T(n, m) = T(n-1, m) + T(n, m-1) + T(n-1, m-1)
We can discover that the equation is quite similar to the recursive equation of binomial coefficient, but with even larger result. This tells us that the time complexity of the algorithm is an exponential function, which is quite slow.
But actually, you can use some tricks to reduce its time complexity to O(mn).
bool calculated[MAX_M][MAX_N];
int answer[MAX_M][MAX_N]
static int F(int m, int n)
{
if (n == 0 || m == 0)
return n + m;
else
{
if (calculated[m][n] == false)
{
answer[m][n] = Math.Min((1 + F(m - 1, n)), Math.Min((1 + F(m, n - 1)), (D(m - 1, n - 1) + F(m - 1, n - 1))));
calculated[m][n] = true;
}
return answer[m][n];
}
}
I can't quite understand what the second piece of code is going to do as there are lots of functions unprovided in your code. Maybe you can explain that a bit?

Explanation of the following algorithm to find nCr modulo P

I was trying to solve a problem involving large factorials modulo a prime, and found the following algorithm in another's solution:
long long factMod (long long n, long long p)
{
long long ans = 1;
while (n > 1)
{
long long cur = 1;
for (long long i = 1; i < p; i++)
{
cur = (cur * i) % p;
}
ans = (ans * modPow(cur, n/p, p)) % p;
for (long long i = 1; i <= n % p; i++)
{
ans = (ans * i) % p;
}
n /= p;
}
return (ans % p);
}
long long nChooseK(long long n, long long k, long long p)
{
int num_degree = get_degree(n, p) - get_degree(n - k, p);
int den_degree = get_degree(k, p);
if (num_degree > den_degree) { return 0; }
long long nFact = factMod(n, p);
long long kFact = factMod(k, p);
long long nMinusKFact = factMod(n-k, p);
long long ans = (((nFact * modPow(kFact, p - 2, p)) % p) * modPow(nMinusKFact, p - 2, p))%p;
return ans;
}
I know the basics of number theory but can't seem to figure out how this works.
The nChooseK function appears to use the definition of combination [n!/(n-k)!k!] with the modular inverse computed using Fermat's little theorem to replace the division. However, according to one of the answers, the factMod function does not actually compute the factorial. If this is the case, how does the nChooseK function work?
Yes, n! ≡ 0 mod p if and only if n ≥ p, but factMod isn't computing n! mod p – it's computing n!/pk mod p where k is the exponent of p in the prime factorization of n!, perhaps for the purpose of computing a binomial coefficient. Iteration i (counting from 0) of the loop counts the contribution of those factors 1…n whose prime factorization includes pi. The statement n /= p; yields the subproblem on the multiples of p.
The function get_degree(n, p) presumably returns the exponent of p in the prime factorization of n!. If get_degree(n, p) == get_degree(k, p) + get_degree(n - k, p), then the factors of p in numerator and denominator exactly cancel, and we can use factMod to account for the other factors. Otherwise, the number of combinations is divisible by p, so we return 0.
Since (p-1)! ≡ -1 mod p by Wilson's theorem, the first inner loop is redundant.

Calculating the big-O complexity of this selection sort implementation?

I'm trying to compute the big-O time complexity of this selection sort implementation:
void selectionsort(int a[], int n)
{
int i, j, minimum, index;
for(i=0; i<(n-1); i++)
{
minimum=a[n-1];
index=(n-1);
for(j=i; j<(n-1); j++)
{
if(a[j]<minimum)
{
minimum=a[j];
index=j;
}
}
if (i != index)
{
a[index]=a[i];
a[i]=minimum;
}
}
}
How might I go about doing this?
Formally, you can obtain the exact number of iterations with the order of growth using the methodology below:
Executing the following fragment code (synthetic version of the original code), sum will equal the closed form of T(n).
sum = 0;
for( i = 0 ; i < ( n - 1 ) ; i ++ ) {
for( j = i ; j < ( n - 1 ) ; j ++ ) {
sum ++;
}
}
Let's begin by looking at the inside of the outer loop. It does O(1) work with the initial assignments, then has a loop that runs n - i times, then does O(1) more work at the end to perform the swap. Therefore, the runtime is Θ(n - i).
If we sum up from i going from 0 up to n - 1, we get the following:
n + (n - 1) + (n - 2) + ... + 1
This famous sum works out to Θ(n2), so the runtime would be Θ(n2), matching the known runtime of this algorithm.
Hope this helps!

Resources