I'm trying to find growth function of given code.
int sum = 0;
for (int k = n; k > 0; k /= 2) {
cout<<k<<endl;
for (int i = 0; i < k; i++)
{
sum++;
cout<<i<<endl;
}
}
but I'm stuck in first loop for (int k = n; k > 0; k /= 2) , it's being execute in this way :
for n = 5 , it executes 3 times
n = 10 , 4 times
n = 100 , 7 times
n = 1000 , 10 times
how can I generalize it?
First, 10 is about log_2 of 1000. There are about log_2(n) iterations of the outer loop. However, that doesn't tell you the total number of steps because you do a variable number of steps inside.
n + n/2 + n/4 + n/8 + ... = 2n = O(n). You are doing a constant number of things inside the loops, so the total number of steps is O(n). About half of the time is spent on the first iteration of the outer loop, when k=n.
At each step k is divided by two, cut in halves. How many cuts do you need to go to zero?
After 1 cut you have n/2.
After 2 cuts you have n/4.
After 3 cuts you have n/8.
After 4 cuts you have n/16.
After 5 cuts you have n/32.
After x cuts you have n/2x.
So, how long until n = 2x?
Answer is simple: x = log2(n).
Your loop runs at log n times.
But the inner loop runs on the size of these parts. The first run is of size n, the second is n/2, the third is n/4 and so on. The sum of all runs of this inner loop is:
n + n/2 + n/4 + n/8 + ... = 2n.
Thus the total run time equals O(n) (thanks Douglas Zare!)
Related
Problem Statement:
Given an array “A” of N integers and you have also defined the new
array “B” as a concatenation of array “A” for an infinite number of
times. For example, if the given array “A” is [1,2,3] then, infinite
array “B” is [1,2,3,1,2,3,1,2,3,.......]. Now you are given Q queries,
each query consists of two integers “L“ and “R”. Your task is to find
the sum of the subarray from index “L” to “R” (both inclusive) in the
infinite array “B” for each query.
vector<int> sumInRanges(vector<int> &arr, int n, vector<vector<long long>> &queries, int q) {
vector<int> ans;
for(int i=0; i<q; i++){
int l = queries[i][0];
int r = queries[i][1];
int sum = 0;
for(int j=l-1; j<r; j++){
sum += arr[j%n];
}
ans.push_back(sum);
}
return ans;
}
One test case is failing. Could someone suggest the edit required?
Good I've found link to your actual problem.
Take a look on note:
Sum Of Infinite Array
Note :
The value of the sum can be very large, return the answer as modulus 10^9+7.
....
Constraints :
1 <= T <= 100
1 <= N <= 10^4
1 <= A[i] <= 10^9
1 <= Q <= 10^4
1 <= L <= R <= 10^18
Time Limit: 1sec
So basically your code have problem with integer overflow.
Your implementation is to simple. You have to leverage fact that this infinitive array has a period otherwise your code never meets time requirement. You do not have to calculate sum of the all indexes, you can skip a lot and calculate correction using multiplication (modulo).
Your solution takes time proportional to l - r because it tries every number.
But this is unnecessary, as there are n identical periods that you can sum in a single go. So the running time can be made proportional to the length of A instead. (Find the multiple of the length just above or on l and the multiple just below r.)
E.g. to sum from 10 to 27 inclusive, use
1231231231|231231231231231231|23123123... = 1231231231|23+4x123+1|23123123...
I know that a reverse ordered list should yield theta(n^2) number of comparisons and theta(n^2) number of exchanges for bubble sort. In my sample code I am using a list of size n = 10. I implemented counters for the numComparisons and numExchanges, and although this doesn't seem very complicated, I can't figure out why my results don't yield 100 comparisons and 100 exchanges. Am I really far off target?
void testList::bubbleSort()
{
int k = 10;
bool flag = true;
while(flag)
{
k = k - 1;
flag = false;
for(int j = 0; j < k; j++)
{
if( vecPtr[j] > vecPtr[j+1])
{
int temp = vecPtr[j];
vecPtr[j] = vecPtr[j+1];
vecPtr[j+1] = temp;
numExchanges += 1;
flag = true;
}
numComparisons++;
}
}
}
The resulting output:
Original List: 10 9 8 7 6 5 4 3 2 1
Sorted List: 1 2 3 4 5 6 7 8 9 10
Comparisons: 45
Exchanges: 45
I also tried this implementation, but my results were the same:
void testList::bubbleSort()
{
int temp;
for(long i = 0; i < 10; i++)
{
for(long j = 0; j < 10-i-1; j++)
{
if (vecPtr[j] > vecPtr[j+1])
{
temp = vecPtr[j];
vecPtr[j] = vecPtr[j+1];
vecPtr[j+1] = temp;
numExchanges++;
}
numComparisons++;
}
}
}
Approximately N2/2 comparisons and exchanges are expected.
In particular, the inner loop starts the current value of the outer loop. So, on the first iteration, it traverses the entire array. On each subsequent iteration, it traverses one fewer item in the array.
So, the number of iterations of the inner loop is N + N-1 + N-2 ... 1. On average, that's approximately N/2.
If you want to get more precise, there's one more detail to consider: the inner loop iterates from i+1...N, so its largest value is N-1 iterations, not N iterations.
Therefore, instead of being precisely N2/2, it's really N * (N-1)/2. In your case, that 10*9/2 = 45.
That's the count for the number of comparisons. For swaps, you get some percentage of that, depending on the number of items that are out of order. In your specific case, all items are always out of order (because you're starting with reverse order) so you do a swap for every comparison. With any other ordering, you'd expect the number of swaps to be reduced.
45 = 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, so for the exchanges this is correct, but for the comparisons I think there must be a mistake somewhere. Edit: You implemented a slightly more intelligent version than the standard bubble sort, that's why you have only 45 comparisons instead of 90 (it's not 100, one iteration takes 9 comparisons).
I have written this code which has an execution time of 3.664 sec but the time limit is 3 seconds.
The question is this-
N teams participate in a league cricket tournament on Mars, where each
pair of distinct teams plays each other exactly once. Thus, there are a total
of (N × (N1))/2 matches. An expert has assigned a strength to each team,
a positive integer. Strangely, the Martian crowds love onesided matches
and the advertising revenue earned from a match is the absolute value of
the difference between the strengths of the two matches. Given the
strengths of the N teams, find the total advertising revenue earned from all
the matches.
Input format
Line 1 : A single integer, N.
Line 2 : N space separated integers, the strengths of the N teams.
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int stren[200000];
for(int a=0;a<n;a++)
cin>>stren[a];
long long rev=0;
for(int b=0;b<n;b++)
{
int pos=b;
for(int c=pos;c<n;c++)
{
if(stren[pos]>stren[c])
rev+=(long long)(stren[pos]-stren[c]);
else
rev+=(long long)(stren[c]-stren[pos]);
}
}
cout<<rev;
}
Can you please give me a solution??
Rewrite your loop as:
sort(stren);
for(int b=0;b<n;b++)
{
rev += (2 * b - n + 1) * static_cast<long long>(stren[b]);
}
Live code here
Why does it workYour loops make all pairs of 2 numbers and add the difference to rev. So in a sorted array, bth item is subtracted (n-1-b) times and added b times. Hence the number 2 * b - n + 1
There can be 1 micro optimization that possibly is not needed:
sort(stren);
for(int b = 0, m = 1 - n; b < n; b++, m += 2)
{
rev += m * static_cast<long long>(stren[b]);
}
In place of the if statement, use
rev += std::abs(stren[pos]-stren[c]);
abs returns the positive difference between two integers. This will be much quicker than an if test and ensuing branching. The (long long) cast is also unnecessary although the compiler will probably optimise that out.
There are other optimisations you could make, but this one should do it. If your abs function is poorly implemented on your system, you could always make use of this fast version for computing the absolute value of i:
(i + (i >> 31)) ^ (i >> 31) for a 32 bit int.
This has no branching at all and would beat even an inline ternary! (But you should use int32_t as your data type; if you have 64 bit int then you'll need to adjust my formula.) But we are in the realms of micro-optimisation here.
for(int b = 0; b < n; b++)
{
for(int c = b; c < n; c++)
{
rev += abs(stren[b]-stren[c]);
}
}
This should give you a speed increase, might be enough.
An interesting approach might be to collapse down the strengths from an array - if that distribution is pretty small.
So:
std::unordered_map<int, int> strengths;
for (int i = 0; i < n; ++i) {
int next;
cin >> next;
++strengths[next];
}
This way, we can reduce the number of things we have to sum:
long long rev = 0;
for (auto a = strengths.begin(); a != strengths.end(); ++a) {
for (auto b = std::next(a), b != strengths.end(); ++b) {
rev += abs(a->first - b->first) * (a->second * b->second);
// ^^^^ stren diff ^^^^^^^^ ^^ number of occurences ^^
}
}
cout << rev;
If the strengths tend to be repeated a lot, this could save a lot of cycles.
What exactly we are doing in this problem is: For all combinations of pairs of elements, we are adding up the absolute values of the differences between the elements of the pair. i.e. Consider the sample input
3 10 3 5
Ans (Take only absolute values) = (3-10) + (3-3) + (3-5) + (10-3) + (10-5) + (3-5) = 7 + 0 + 2 + 7 + 5 + 2 = 23
Notice that I have fixed 3, iterated through the remaining elements, found the differences and added them to Ans, then fixed 10, iterated through the remaining elements and so on till the last element
Unfortunately, N(N-1)/2 iterations are required for the above procedure, which wouldn't be ok for the time limit.
Could we better it?
Let's sort the array and repeat this procedure. After sorting, the sample input is now 3 3 5 10
Let's start by fixing the greatest element, 10 and iterating through the array like how we did before (of course, the time complexity is the same)
Ans = (10-3) + (10-3) + (10-5) + (5-3) + (5-3) + (3-3) = 7 + 7 + 5 + 2 + 2 = 23
We could rearrange the above as
Ans = (10)(3)-(3+3+5) + 5(2) - (3+3) + 3(1) - (3)
Notice a pattern? Let's generalize it.
Suppose we have an array of strengths arr[N] of size N indexed from 0
Ans = (arr[N-1])(N-1) - (arr[0] + arr[1] + ... + arr[N-2]) + (arr[N-2])(N-2) - (arr[0] + arr[1] + arr[N-3]) + (arr[N-3])(N-3) - (arr[0] + arr[1] + arr[N-4]) + ... and so on
Right. So let's put this new idea to work. We'll introduce a 'sum' variable. Some basic DP to the rescue.
For i=0 to N-1
sum = sum + arr[i]
Ans = Ans + (arr[i+1]*(i+1)-sum)
That's it, you just have to sort the array and iterate only once through it. Excluding the sorting part, it's down to N iterations from N(N-1)/2, I suppose that's called O(N) time EDIT: That is O(N log N) time overall
Hope it helped!
Hello everyone I trying to calculate the time complexity of Maximum Subsequence Sum.
Actually I know the answer which is O(n^3) and it follows from the function (n^3 + 3n^2 + 2n)/6
My question is how is that function obtained.
Quite simply, actually: just look at the loops in the code.
for (int i=0; i<n; i++)
for(j = i; j<n; j++) {
...
for (int k=i; k<=j; k++)
XXX;
The line XXX is executed n^3 times (modulo some constant factor and some lower powers of n), since the outer loop obviously runs from 0 to n-1, the "middle" loop runs from i (which will start out with 0, 1, ...) to n-1, meaning that the inner loop will be "started" approx n^2 times. Now, both i and j depend on n (eg., i will be 0 and j=n-1 at the end of the first outer iteration), so line XXX will be n times (for the inner loop) by n^2 times (for the outer two loops), resulting in a total of n^3.
To get the concrete function (n^3 + 3n^2 + 2n)/6, you'd have to be more thorough in your calculation and take care of all those factors I simply omitted above.
Here is how..
i=0
j=0 k=0 (count=1 )
j=1 k=0,1 (count =2)
j=2 k=0,1,2 (count = 3)
...
j=n-1 k=0,1,2,...n-1 (count = n)
Total number of times code executed = 1+2+3+...+n = n(n+1)/2
i=1
j=1 k=1 (count=1 )
j=2 k=1,2 (count =2)
j=3 k=1,2, 3 (count = 3)
...
j=n-1 k=1,2,...n-1 (count = n-2)
Total number of times code executed = 1+2+3+...+n-1 = (n-1)n/2
...
i=n-1
j=n-1 k=n-1 ( count = 1)
Total number of of times code executed = 1 = 1(1+1)/2
Now if we sum for all the values of i
n(n+1)/2 + ((n-1)((n-1)+1)/2+.....+1(1+1)/2
=∑ N(N+1)/2 =1/2∑(N^2 +N) =1/2(∑N^2+∑N)=1/2{ 1/6 N(N+1)(2N+1) + 1/2 N(N+1) } =1/2{ (2N^3 + 3N^2+N )/6 +(N^2+N)/2} =(N^3 + 3N^2 + 2N)/6
Check this solution suggested by Mark Allen Weiss (in his book).
Consider the following loop:
for (i =1; i <= n; i++) {
for (j = 1; j <= i; j++) {
k = k + i + j;
}
}
The outer loop executes n times. For i= 1, 2, ..., the inner loop is executed one time, two times, and
n times. Thus, the time complexity for the loop is
T(n)=c+2c+3c+4c...nc
=cn(n+1)/2
=c/2(n^2)+c/2n
=O(n^2)..
Ok so I don't understand how the time complexity, T(n) even determines c+2c+3c. etc.. and then cn(n+1)/2? Where did that come from?
The sum 1 + 2 + 3 + 4 + ... + n is equal to n(n+1)/2, which is the Gauss series. Therefore,
c + 2c + 3c + ... + nc
= c(1 + 2 + 3 + ... + n)
= cn(n+1) / 2
This summation comes up a lot in algorithmic analysis and is useful to know when working with big-O notation.
Or is your question where the summation comes from at all?
Hope this helps!