I'm trying to calculate the total number of times the innermost statement is executed.
count = 0;
for i = 1 to n
for j = 1 to n - i
count = count + 1
I figured that the most the loop can execute is O(n*n-i) = O(n^2). I wanted to prove this by using double summation but I'm getting lost since the I'm having trouble starting the equation since j = 1 is thrown into there.
Can someone help me explain this to me?
Thanks
For each i, the inner loop executes n - i times (n is constant). Therefore (since i ranges from 1 to n), to determine the total number of times the innermost statement is executed, we must evaluate the sum
(n - 1) + (n - 2) + (n - 3) + ... + (n - n)
By rearranging the terms (grouping all the ns that appear first), we can see that this is equal to
n*n - (1 + 2 + 3 + ... + n) = n*n - n(n+1)/2 = n*(n-1)/2 = n*n/2 - n/2
Here's a simple implementation in Python to verify this:
def f(n):
count = 0;
for i in range(1, n + 1):
for _ in range(1, n - i + 1):
count = count + 1
return count
for n in range(1,11):
print n, '\t', f(n), '\t', n*n/2 - n/2
Output:
1 0 0
2 1 1
3 3 3
4 6 6
5 10 10
6 15 15
7 21 21
8 28 28
9 36 36
10 45 45
The first column is n, the second is the number of times that inner statement is executed, and the third is n*n/2 - n/2.
Related
I'm having trouble understanding the meaning of a function f(x) representing the number of operations performed in some code.
int sum = 0; // + 1
for (int i = 0; i < n; i++)
for (int j = 1; j <= i; j++)
sum = sum + 1; // n * (n + 1) / 2
(Please note that there is no 2 in the numerator on that last comment, but there is in the function below.)
Then my notes say that f(x) = 2n(n + 1) / 2 + 1 = O(n^2)
I understand that because there are two for loops, that whatever f(x) is, it will be = O(n^2), but why is the time estimate what it is? How does the j<= i give you n*(n+1)? What about the 2 in the denominator?
Think about, across the entire execution of this code, how many times the inner loop will run. Notice that
when i = 0, it runs zero times;
when i = 1, it runs one time;
when i = 2, it runs two times;
when i = 3, it runs three times;
...; and
when i = n - 1, it runs n - 1 times.
This means that the total number of times the innermost loop runs is given by
0 + 1 + 2 + 3 + 4 + ... + (n - 1)
This is a famous summation and it solves to
0 + 1 + 2 + 3 + 4 + ... + (n - 1) = n(n - 1) / 2
This is the n - 1st triangular number and it's worth committing this to memory.
The number given - n(n + 1) / 2 - seems to be incorrect, but it's pretty close to the true number. I think they assumed the loop would run 1 + 2 + 3 + ... + n times rather than 0 + 1 + 2 + ... + n - 1 times.
From this it's a bit easier to see where the O(n2) term comes from. Notice that n(n - 1) / 2 = n2 / 2 - n / 2, so in big-O land where we drop constants and low-order terms we're left with n2.
Given a pyramid like:
0
1 2
3 4 5
6 7 8 9
...
and given the index of the pyramid i where i represents the ith number of the pyramid, is there a way to find the index of the row to which the ith element belongs? (e.g. if i = 6,7,8,9, it is in the 3rd row, starting from row 0)
There's a connection between the row numbers and the triangular numbers. The nth triangular number, denoted Tn, is given by Tn = n(n-1)/2. The first couple triangular numbers are 0, 1, 3, 6, 10, 15, etc., and if you'll notice, the starts of each row are given by the nth triangular number (the fact that they come from this triangle is where this name comes from.)
So really, the goal here is to determine the largest n such that Tn ≤ i. Without doing any clever math, you could solve this in time O(√n) by just computing T0, T1, T2, etc. until you find something bigger than i. Even better, you could binary search for it in time O(log n) by computing T1, T2, T4, T8, etc. until you overshoot, then binary searching on the range you found.
Alternatively, we could try to solve for this directly. Suppose we want to find the choice of n such that
n(n + 1) / 2 = i
Expanding, we get
n2 / 2 + n / 2 = i.
Equivalently,
n2 / 2 + n / 2 - i = 0,
or, more easily:
n2 + n - 2i = 0.
Now we use the quadratic formula:
n = (-1 ± √(1 + 8i)) / 2
The negative root we can ignore, so the value of n we want is
n = (-1 + √(1 + 8i)) / 2.
This number won't necessarily be an integer, so to find the row you want, we just round down:
row = ⌊(-1 + √(1 + 8i)) / 2⌋.
In code:
int row = int((-1 + sqrt(1 + 8 * i)) / 2);
Let's confirm that this works by testing it out a bit. Where does 9 go? Well, we have
(-1 + √(1 + 72)) / 2 = (-1 + √73) / 2 = 3.77
Rounding down, we see it goes in row 3 - which is correct!
Trying another one, where does 55 go? Well,
(-1 + √(1 + 440)) / 2 = (√441 - 1) / 2 = 10
So it should go in row 10. The tenth triangular number is T10 = 55, so in fact, 55 starts off that row. Looks like it works!
I get row = math.floor (√(2i + 0.25) - 0.5) where i is your number
Essentially the same as the guy above but I reduced n2 + n to (n + 0.5)2 - 0.25
I think ith element belongs nth row where n is number of n(n+1)/2 <= i < (n+1)(n+2)/2
For example, if i = 6, then n = 3 because n(n+1)/2 <= 6
and if i = 8, then n = 3 because n(n+1)/2 <= 8
Here is my code:
let rec sum n =
if n <= 0 then 0
else if n / 2 * 2 = n then 3 * n + 50 * (sum n-2)
else n + 10 * (sum n-1);;
The math problem is simply as following:
sn =
0 if n = 0
50*sn-2 + 3*n, if n > 0 and n is even
10*sn-1 + n , if n > 0 and n is odd
When I test sum 5, it popped out "stack overflow" error as following:
Stack overflow during evaluation (looping recursion?).
Could anyone help me out?
That is because n is not being changed in the recursive call. You'll have to wrap the n-1 and n-2 in parenthesis. You're calling (sum n)-1 instead of sum (n-1).
Add parentheses:
let rec sum n =
if n <= 0 then 0
else if n / 2 * 2 = n then 3 * n + 50 * (sum (n-2))
else n + 10 * (sum (n-1));;
(* prints 3125 *)
print_int (sum 5);;
Instead of calling sum on n-2 (or n-1), you're calling it on n and subtracting 2 (or 1) from the result. Since the input never changes, it recurses until it overflows the stack.
If we have M as follows:
M = 1+2+3+5+6+7+9+10+11+13+...+n
What would be the QBasic program to find M.
I have done the following so far, but is not returning me the expected value
INPUT "ENTER A VALUE FOR N"
SUM = 0
FOR I = 1 TO N
IF I MOD 4 = 0
SUM = SUM + I
NECT I
How should I go about this?
Thanks.
You have mixed the equality operator. Try this:
INPUT "ENTER A VALUE FOR N"
SUM = 0
FOR I = 1 TO N
IF I MOD 4 <> 0
SUM = SUM + I
NEXT I
No need to write a program, or at least no need to use loops.
Sum of first n natural numbers:
sum_1 = n * (n + 1) / 2
Sum of multiples of 4 < n:
sum_2 = 4 * (n / 4) * (n / 4 + 1) / 2 = 2 * (n / 4) * (n / 4 + 1)
The result is sum_1 - sum_2:
sum = sum_1 - sum_2 = n * (n + 1) / 2 - 2 * (n / 4) * (n / 4 + 1)
NB: / = integer division
This snip calculates the sum of integers to n skipping values divisible by 4.
PRINT "Enter upper value";
INPUT n
' calculate sum of all values
FOR l = 1 TO n
x = x + l
NEXT
' remove values divisible by 4
FOR l = 0 TO n STEP 4
x = x - l
NEXT
PRINT "Solution is:"; x
Suppose we have a set like {1,2,3} then there is only one way to choose 3 consecutive numbers... it's the set {1,2,3}...
For a set of {1,2,3,4} we have 3 ways: 123 234 1234
(technically these are unordered sets of numbers, but writing them consecutively helps)
f(5) ; {1,2,3,4,5} -> 8 ways: 123 1234 1235 12345 234 2345 345 1345
f(6) ; {1,2,3,4,5,6} -> 20 ways: ...
f(7) ; {1,2,3,4,5,6,7} -> 47 ways: ...
So for a given N, I can get the answer by applying brute force, and calculating all such subset having 3 or more consecutive number.
Here I am just trying to find out a pattern, a technique to get the number of all such subset for a given N.
The problem is further generalized to .....discover m consecutive number within a set of size N.
There is a bijection between this problem and "the number of N-digit binary numbers with at least three consecutive 1s in a row somewhere" (the bijection being a number is 0 if excluded in the subset, and 1 if included in the subset).
This is a known problem, and should be enough information to google for a result, if you search for number of n-digit binary strings with m consecutive 1s, the second hit is Finding all n digit binary numbers with r adjacent digits as 1
Alternatively you can just look it up as http://oeis.org/search?q=0%2C0%2C1%2C3%2C8%2C20%2C47 (based on the brute-forcing you did for the first few terms) - resulting in an explicit formula of 2^n - tribonacci(n+3), see here for an explicit formula for tribonacci numbers. It also gives a recurrence relation. The analogy given is "probability (out of 2^n) of getting at least 1 run of 3 heads within n flips of a fair coin"
I can only assume that the answer to the general problem is 2^n - Fm(n+m), where Fm is the mth n-step Fibonacci number (edit: that does seem to be the case)
This sounds like homework to me, so I'll just get you started. FoOne approach is to think of the Lowest and Highest members of the run, L and H. If the set size is N and your minimum run length is M, then for each possible position P of L, you can work out how many positions of H there are....
With a bit of python code, we can investigate this:
y = set()
def cons(li, num):
if len(li) < num:
return
if len(li) == num:
y.add(tuple([i for i in li]))
else:
y.add(tuple([i for i in li]))
cons(li[1:], num)
cons(li[:-1], num)
This solution will be quite slow (it's exponential in complexity, actually), but try it out for a few small list sizes and I think you should be able to pick up the pattern.
Not sure if you mean consecutive or not. If not, then for {1, 2, 3, 4} there are 4 possibilities: {1, 2, 3} {2, 3, 4} {1, 3, 4} {1, 2, 3, 4}
I think you can calculate the solution with N!/3! where N! = N*(N-1)(N-2)...*1.
Quick answer:
Sequences(n) = (n-1)*(n-2) / 2
Long answer:
You can do this by induction. First, I'm going to re-state the problem, because your problem statement isn't clear enough.
Rule 1: For all sets of consecutive numbers 1..n where n is 2 or more
Rule 2: Count the subsets S(n) of consecutive numbers m..m+q where q is 2 or more
S(n=3)
By inspection we find only one - 123
S(n=4)
By inspection we find 3! - 123 234 and 1234
Note that S(4) contains S(3), plus two new ones... both include the new digit 4... hmm.
S(n=5)
By inspection we find ... S(n=4) as well as 345 2345 and 12345. That's 3+3=6 total.
I think there's a pattern forming here. Let's define a new function T.
Rule 3: S(n) = S(n-1) + T(n) ... for some T.
We know that S(n) contains the digit n, and should have spotted by now that S(n) also contains (as a subcomponent) all sequences of length 3 to n that include the digit n. We know they cannot be in S(n-1) so they must be in T(n).
Rule 4: T(n) contains all sequence ending in n that are of length 3 to n.
How many sequences are in S(n)?
Let's look back at S(3) S(4) and S(5), and incorporate T(n):
S(3) = S(3)
S(4) = S(3) + T(4)
S(5) = S(4) + T(5) = S(3) + T(4) + T(5)
let's generalise:
S(n) = S(3) + T(f) for all f from 4 to n.
So how many are in a given T?
Look back at rule 5 - how many sequences does it describe?
For T(4) it describes all sequences 3 and longer ending in 4. (that's 234)
For T(5) it describes all sequences 3 and longer ending in 5. (that's 345 2345 = 2)
T count Examples
4 2 1234 234
5 3 12345 2345 345
6 4 123456 23456 3456 456
Looks awfully like T(n) is simply n-2!
So
S(6) = T(6) + T(5) + T(4) + S(3)
10 = 4 + 3 + 2 + 1
And
S(7) = 15 = 5 + 4 + 3 + 2 + 1
S(8) = 21 = 6 + 5 + 4 + 3 + 2 + 1
Turning this into a formula
What's 2 * S(8)?
42 = 6 + 5 + 4 + 3 + 2 + 1 + 1 + 2 + 3 + 4 + 5 + 6
Add each pair of biggest and smallest numbers:
42 = 7 + 7 + 7 + 7 + 7 + 7
42 = 7 * 6
But that's 2 * S(8), so
S(8) = 42/2 = 21 = 7 * 6 / 2
This generalizes:
S(n) = (n-1)*(n-2) / 2
Let's check this works:
S(3) = 2*1/2 = 1
S(4) = 3*2/2 = 3
S(5) = 4*3/2 = 6
S(6) = 5*4/2 = 10
I'm satisfied.