What will be the time complexity of this algorithm by frequency count method? - c++

Following is the code:
for (i = n-1; i>0; i--)
for (j=0; j<i; j++)
if (arr[i] < arr[i+1])
{
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
I could find for the outer for outer for loop will execute n times and the inner for loop will be executed i+i-1+i-2+....+1 i(i+1)/2=(i^2+i)/2 and the if condition will be checked for (i-1)*i/2=(i^2-i)/2 times but I am confused for the statements in if condition and also correct me if I am wrong for the my above calculations too.

for n = 5, the values of i and j encountered when the if statement is executed can be listed as follows:
(4,0) (4,1) (4,2) (4,3)
(3,0) (3,1) (3,2)
(2,0) (2,1)
(1,0)
I arranged the items like that on purpose because they form a triangle.
####
###
##
#
To count how many items are in this triangle we can mirror the triangle and count each item twice. There are two ways to do it neatly depending on whether you place the mirrored items to the right or below.
####o
###oo
##ooo
#oooo
####
###o
##oo
#ooo
oooo
Either way, by inspecting width times height, this can easily be seen to be a rectangle of either n * (n-1) or (n-1) * n items (equal area in both cases). And since we counted each element twice, we can divide by two, and use (n-1) * n / 2 as the formula for the number of items.
Therefore your if condition will be computed exactly (n-1) * n / 2 times.
You also correctly expanded this expression to be ((n*n) - (n)) / 2 which is also equal to (n^2 - n) / 2.
But a few things were bad...
You said (i-1)*i/2, using i instead of n. That's not right.
Your code appears to intend to compute a Bubble sort. And the index for the if condition and its block should be j (not i) throughout. (You were comparing arr[i] to arr[i+1] for the same value of i repeatedly in the inner loop. The actual swap would be evaluated at most once for a given value of i, in that case, or not at all, depending on the values of arr.)
The code you intended was likely:
for (i = n-1; i>0; i--)
for (j=0; j<i; j++)
if (arr[j] < arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}

Related

Why do we make n-1 iterations in bubble sort algorithm

Most common way of bubble sort algorithm is to have two for loops. Inner one being done from j=0 until j n-i-1. I assume we substract minus i, because when we reach last element we don't compare it because we don't have an element after him. But why do we use n-1. Why we don't run outer loop from i=0 until i < n and inner from j=0 until n-i? Could someone explain it to me, tutorials on internet does not emphasize this.
for (int i = 0; i < n - 1; i++) // Why do we have n-1 here?
{
swapped = false;
for (int j = 0; j < n - i - 1; j++)
{
countComparisons++;
if (arr[j] > arr[j + 1])
{
countSwaps++;
swap(&arr[j], &arr[j + 1]);
swapped = true;
}
}
}
For example, if I have an array with 6 elements, why do I only need to make 5 iterations?
Because a swap requires at least two elements.
So if you have 6 elements, you only need to consider 5 consecutive pairs.
For comparison purposes in an array, two adjacent cells are needed; in an array of 6 elements, you do 5 comparisons only; in an array of 10 elements, 9 comparisons, and so on:
array and comparisons between adjacent cells
So for 7 elements, just 6 comparisons are done, hence the general rule of n-1 in the outer for loop
About the n-1-i expression, remember that the highest (or lowest, depending on the ordering criterion) value in the bubble sort goes to the last position in the array after the first cycle, so there is no need to compare that value with anything else, therefore the array has to be "shortened" 1 cell at a time, and the value of i in the outer loop is the counter responsible for that in the inner loop:
5 | 3 | 9 | 20 | elements (n) = 4
after first cycle (i = 0), 20 has reached its correct position within the array (using an ascending order), leaving us with an array of 3 elements to do comparisons to; in next cycle, i will be equal to 1, and as n-1 remains the same, we need to substract 1 in that expression to "shorten" the array:
n-1-i = 4-1-1 = 2, which is the index of the last element in that new array as well as the quantity of comparisons needed.
Hope it helps!

Number of paths in mXn grid

Is there a way to find the number of paths in mXn grid moving one cell at a time either downward, right or diagonally down-right using Permutation, starting from (1,1) and reaching (m,n)? I know there is a straight-forward DP solution and also P&C solution (i.e. m+n-2Cn-1) if the movement is only downward and right.
Look up Delannoy numbers. The combinatoric solution is expressed as a sum of multinomials.
Let t be the number of diagonal moves, the equation becomes:
This just needs a slight extension to the already existing solution DP solution that computes the path allowing movements only downwards and rightwards.
The only change you need to make is to count the number of ways you can reach a point if you move diagonally as well.
The code I took from http://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/ should help you understand it better.
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// Create a 2D table to store results of subproblems
int count[m][n];
// Count of paths to reach any cell in first column is 1
for (int i = 0; i < m; i++)
count[i][0] = 1;
// Count of paths to reach any cell in first column is 1
for (int j = 0; j < n; j++)
count[0][j] = 1;
// Calculate count of paths for other cells in bottom-up manner using
// the recursive solution
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
// Rightwards Downwards Diagnoally right
count[i][j] = count[i-1][j] + count[i][j-1] + count[i-1][j-1];
}
return count[m-1][n-1];
}

Given a sorted array and a parameter k, find the count of sum of two numbers greater than or equal to k in linear time

I am trying to find all pairs in an array with sum equal to k. My current solution takes O(n*log(n)) time (code snippet below).Can anybody help me in finding a better solution, O(n) or O(lgn) may be (if it exists)
map<int,int> mymap;
map<int,int>::iterator it;
cin>>n>>k;
for( int i = 0 ; i < n ; i++ ){
cin>>a;
if( mymap.find(a) != mymap.end() )
mymap[a]++;
else
mymap[a] = 1;
}
for( it = mymap.begin() ; it != mymap.end() ; it++ ){
int val = it->first;
if( mymap.find(k-val) != mymap.end() ){
cnt += min( it->second, mymap.find(k-val)->second );
it->second = 0;
}
}
cout<<cnt;
Another aproach which will take O(log n) in the best case and O(nlog n) in the worst one for positive numbers can be done in this way:
Find element in array that is equal to k/2 or if it doesn’t exist than finds the minimum greater then k/2. All combinations with this element and all greater elements will be interested for us because p + s >= k when p>= k/2 and s>=k/2. Array is sorted, so binary search with some modifications can be used. This step will take O(log n) time.
All elements which are less then k/2 + elements greater or equal to "mirror elements" (according to median k/2) will also be interested for us because p + s >= k when p=k/2-t and s>= k/2+t. Here we need to loop through elements less then k/2 and find their mirror elements (binary search). The loop should be stopped if mirror element is greater then the last array.
For instance we have array {1,3,5,8,11} and k = 10, so on the first step we will have k/2 = 5 and pairs {5,7}, {8,11}, {8, 11}. The count of these pairs will be calculated by formula l * (l - 1)/2 where l = count of elements >= k/2. In our case l = 3, so count = 3*2/2=3.
On the second step for 3 number a mirror element will be 7 (5-2=3 and 5+2=7), so pairs {3, 8} and {3, 11} will be interested. For 1 number mirror will be 9 (5-4=1 and 5+4=9), so {1, 11} is what we look for.
So, if k/2 < first array element this algorithm will be O(log n).
For negative the algorithm will be a little bit more complex but can be solved also with the same complexity.
There exists a rather simple O(n) approach using the so-called "two pointers" or "two iterators" approach. The key idea is to have two iterators (not necessarily C++ iterators, indices would do too) running on the same array so that if first iterator points to value x, then the second iterator points to the maximal element in the array that is less then k-x.
We will be increasing the first iterator, and while doing this we'll also change the second iterator to maintain this property. Note that as the first pointer increases, the corresponding position of the second pointer will only decrease, so on every iteration we can start from the position where we stopped at the previous iteration; we will never need to increase the second pointer. This is how we achieve O(n) time.
Code is like this (did not test this, but the idea should be clear)
vector<int> a; // the given array
int r = a.size() - 1;
for (int l=0; l<a.size(); l++) {
while ((r >= 0) && (a[r] >= k - a[l]))
r--;
// now r is the maximal position in a so that a[r] < k - a[l]
// so all elements right to r form a needed pair with a[l]
ans += a.size() - r - 1; // this is how many pairs we have starting at l
}
Another approach which might be simpler to code, but a bit slower, is O(n log n) using binary search. For each element a[l] of the array, you can find the maximal position r so that a[r]<k-a[l] using binary search (this is the same r as in the first algorithm).
#Drew Dormann - thanks for the remark.
Run through the array with two pointers. left and right.
Assuming left is the small side, start with left at location 0 and then right moves towards left until a[left]+a[right] >= k for the last time.
When this is achieved, then total_count += (a.size - right + 1).
You then move left one step forwards and right needs to (maybe) move towards it. Repeat this until they meet.
When this is done, and let us say they met at location x, then totla_count += choose(2, a.size - x).
Sort the array (n log n)
for (i = 1 to n)
Start at the root
if a[i] + curr_node >= k, go left and match = indexof(curr_nod)e
else, go right
If curr_node = leaf node, add all nodes after a[match] to the list of valid pairs with a[i]
Step 2 also takes O(n log n). The for loop runs n times. Within the loop, we perform a binary search for each node i.e. log n steps. Hence the overall complexity of the algorithm is O (n log n).
This should do the work:
void count(int A[], int n) //n being the number of terms in array
{ int i, j, k, count = 0;
cin>>k;
for(i = 0; i<n; i++)
for(j = 0; j<n; j++)
if(A[i] + A[j] >= k)
count++ ;
cout<<"There are "<<count<<" such numbers" ;
}

Why can the KMP failure function be computed in O(n) time?

Wikipedia claims that the failure function table can be computed in O(n) time.
Let's look at its `canonical' implementation (in C++):
vector<int> prefix_function (string s) {
int n = (int) s.length();
vector<int> pi (n);
for (int i=1; i<n; ++i) {
int j = pi[i-1];
while (j > 0 && s[i] != s[j])
j = pi[j-1];
if (s[i] == s[j]) ++j;
pi[i] = j;
}
return pi;
}
Why does it work in O(n) time, even if there is an inner while-loop? I'm not really strong at the analysis of algorithms, so may somebody explain it?
This line: if (s[i] == s[j]) ++j; is executed at most O(n) times.
It caused increase in the value of p[i]. Note that p[i] starts at same value as p[i-1].
Now this line: j = pi[j-1]; causes decrease of p[i] by at least one. And since it was increased at most O(n) times (we count also increases and decreases on previous values), it cannot be decreased more than O(n) times.
So it as also executed at most O(n) times.
Thus the whole time complexity is O(n).
There's already two answers here that are correct, but I often think a fully laid out
proof can make things clearer. You said you wanted an answer for a 9-year-old, but
I don't think it's feasible (I think it's easy to be fooled into thinking it's true
without actually having any intuition for why it's true). Maybe working through this answer will help.
First off, the outer loop runs n times clearly because i is not modified
within the loop. The only code within the loop that could run more than once is
the block
while (j > 0 && s[i] != s[j])
{
j = pi[j-1]
}
So how many times can that run? Well notice that every time that condition is
satisfied we decrease the value of j which, at this point, is at most
pi[i-1]. If it hits 0 then the while loop is done. To see why this is important,
we first prove a lemma (you're a very smart 9-year-old):
pi[i] <= i
This is done by induction. pi[0] <= 0 since it's set once in the initialization of pi and never touched again. Then inductively we let 0 < k < n and assume
the claim holds for 0 <= a < k. Consider the value of p[k]. It's set
precisely once in the line pi[i] = j. Well how big can j be? It's initialized
to pi[k-1] <= k-1 by induction. In the while block it then may be updated to pi[j-1] <= j-1 < pi[k-1]. By another mini-induction you can see that j will never increase past pi[k-1]. Hence after the
while loop we still have j <= k-1. Finally it might be incremented once so we have
j <= k and so pi[k] = j <= k (which is what we needed to prove to finish our induction).
Now returning back to the original point, we ask "how many times can we decrease the value of
j"? Well with our lemma we can now see that every iteration of the while loop will
monotonically decrease the value of j. In particular we have:
pi[j-1] <= j-1 < j
So how many times can this run? At most pi[i-1] times. The astute reader might think
"you've proven nothing! We have pi[i-1] <= i-1 but it's inside the while loop so
it's still O(n^2)!". The slightly more astute reader notices this extra fact:
However many times we run j = pi[j-1] we then decrease the value of pi[i] which shortens the next iteration of the loop!
For example, let's say j = pi[i-1] = 10. But after ~6 iterations of the while loop we have
j = 3 and let's say it gets incremented by 1 in the s[i] == s[j] line so j = 4 = pi[i].
Well then at the next iteration of the outer loop we start with j = 4... so we can only execute the while at most 4 times.
The final piece of the puzzle is that ++j runs at most once per loop. So it's not like we can have
something like this in our pi vector:
0 1 2 3 4 5 1 6 1 7 1 8 1 9 1
^ ^ ^ ^ ^
Those spots might mean multiple iterations of the while loop if this
could happen
To make this actually formal you might establish the invariants described above and then use induction
to show that the total number of times that while loop is run, summed with pi[i] is at most i.
From that, it follows that the total number of times the while loop is run is O(n) which means that the entire outer loop has complexity:
O(n) // from the rest of the outer loop excluding the while loop
+ O(n) // from the while loop
=> O(n)
Let's start with the fact the outer loop executes n times, where n is the length of the pattern we seek. The inner loop decreases the value of j by at least 1, since pi[j] < j. The loop terminates at the latest when j == -1, therefore it can decrease the value of j at most as often as it has been increased previously by j++ (the outer loop). Since j++ is executed in the outer loop exactly n times, the overall number of executions of the inner while loop is limited to n. The preprocessing algorithm therefore requires O(n) steps.
If you care, consider this simpler implementation of the preprocessing stage:
/* ff stands for 'failure function': */
void kmp_table(const char *needle, int *ff, size_t nff)
{
int pos = 2, cnd = 0;
if (nff > 1){
ff[0] = -1;
ff[1] = 0;
} else {
ff[0] = -1;
}
while (pos < nff) {
if (needle[pos - 1] == needle[cnd]) {
ff[pos++] = ++cnd;
} else if (cnd > 0) {
cnd = ff[cnd]; /* This is O(1) for the reasons above. */
} else {
ff[pos++] = 0;
}
}
}
from which it is painfully obvious the failure function is O(n), where n is the length of the pattern sought.

Simplest bubble sort possible

Suppose I want to sort an array of integer of size n. Suppose I have the swap method
Is this bubble sort implementation of mine correct?
for(int i=0;i<n;i++)
for (int j=0;j<n;j++)
if (array[i]<array[j]) swap(array[i], array[j]);
(I just want to know if it's correct or not, I don't care about inefficiency)
It's not correct for descending-order sort..
think about array = [2, 1], it output [1, 2]
You can make it correct by change j=0 to j=i+1
for(int i=0;i<n;i++)
for (int j=i+1;j<n;j++)
if (array[i]<array[j]) swap(array[i], array[j]);
But it's correct for ascending-order sort.
Simple proof here:
Suppose after each step for output for loop we have a[0] <= a[1] <= ... <= a[i-1] <= a[i], we call this suppose_i
suppose_i is right when i = 0
If suppose_i is correct for 0 <= i < M <= N. When i = M, we have a[0] <= a[1] <= ... <= a[M - 2] <= a[M - 1]. After inner loop j from 0 to M, we got a[0] <= a[1] <= ... <= a[M - 2] <= a[M - 1] <= a[M]. When continue inner loop j from M+1 to N - 1, a[M] will become even larger. So suppose_i is also correct for i = M.
Yes, it's correct. Proof can be constructed along the following lines.
Always when j-loop (the inner) completes (so j=n, i will be increased as next op), then a[i] is the max, and the part before a[i] is in ascending order (proofs below). So when the outer cycle is about to complete with i=n-1 then a[i] is max, and the items up to the index i are ordered (and since none of the preceding items is greater than max) so the whole array is ordered.
To prove that a[i] is always max after the j-loop is simple: i is not changing while the j-loop and if j encounters an item larger than a[i] then that is brought to a[i] and since j has scanned the whole array it's not possible that it includes an element larger than a[i].
To prove that the items up to i are ordered is full induction. We will use the above statement about a[i] being max.
For i=0 trivial (no preceding elements). a[0] is max and "it is ordered".
i=1 (just for fun): 1 item got to a[0] (don't care about its value, it cannot be greater than max), and a[1] is max. So a[0..1] sorted.
Now if the theses are satisfied after a j-loop ending at i=k then the following happens:
i <- k+1
Let's say the current item a[i]=q.
j scans a[] to k. Since k is the max it will be swapped to i. The items beyond i are not bothered yet. So essentially max moves up by one, so one item, particulaily q was added to the first part of the array. Let's see how:
The sorted part to max is scanned by j until it finds an item at index m that is larger than a[i]. (It will find a[i-1] in the worst case.) The items up to m are sorted. Now a[i] will be inserted here, an all items in the range [m..i-1] will be moved up by one. Since m is a right place to insert a[i] so a[0..i] will be ordered after the move. Now the only thing to prove is that the j-loop in [m..i] really performs a move:
At the beginning the sequence a[i],a[m..i-1] is ordered, thus every comparison in this interval will trigger a swap: a[i] is always the smallest in the a[j..i] part. The swap (i with j) will make the j-th to be at the right place (minimal item to the front) and j steps on to the remaining part of the interval.
So j reaches i=k+1 (no swap here) and a[k+1] is max so no more swaps in this j-loop, so at the end a[0..k+1] is sorted.
So finally if the theses hold for i=k then they hold for i=k+1 after a j-loop. We'we established that they hold for i=0 after 1 j-loop, and from i-loop shows that there will be altogether n j-loops so the theses hold for i=n-1 which is just what we've promised to prove in the firs paragraph.