So I'm not really understanding a few things here, when counting the steps in for(int i = 1; i <= n; i++) the answer is:
1 for assignment int i = 1, n+1 for i <= n and n for i++ which comes out to a total of 2n+2. My confusions is in 3 parts:
1.) Isn't the assignment int i = 1; also n? If lets say, n = 5, won't we end up assigning int i = 2, int i = 3... etc?
2.) For i <= n, is it n+1 because you are performing n checks and + 1 when it's false?
3.) Last, is i++ n because you are performing n additions?
For loop looks like for(INIT; CONDITION; INCREMENT) { /* ... */ }. The INIT part executes once only. This is equivalent to:
INIT
while(CONDITION)
{ /* ... */
INCREMENT
}
The initialization int i=1; is performed only one time at the beginning of the loop, regardless of n.
As for 2) and 3), you are correct.
Related
static void functionF(int n) {
for (int i = 0; i < n; i++) {
functionF(n-1);
}
}
I've calculated that:
if n = 2, the function gets called 4 more times. If n = 3, it gets called 15 more times. If n = 4, it gets called 64 more times. I am trying to work out a big O time complexity.
From a complexity pov, it takes factorial time to complete -> O(n!)
Because every step, would run the amount of times specified in the last step.
And note the diference between your function and:
function alpha(n){
for(int i = 0; i < n; n++){
//Do some stuff
alpha(i)
}
}
or
function alpha(n){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
// Do some stuff
}
}
}
The first one i can't really guess its time, buts lower than O(n!)
The second one is the simple O(n²), which in any real situacion runs faster than O(n!)
Tested this function by incrementing a public static variable every time the function is called. You could do this in the future if you want to check how many times something is done.
The pattern beginning with (1, 4, 15, 64, 325, ...) is:
a(n) = n(a(n-1) + 1)
or
a(n) = n(a(n-1)) + n
That's such an odd function because of the recursive aspect of it. However, it's accurate. You could have searched this pattern up from the numbers you provided, as well.
If I input a string str and an int n, I need to create a loop that will print the beginning of the string n times, with the first n chars, then the first n - 1, then n - 2, and so on, until it prints just the first character.
So for example, "Apples" and "3" would result in "AppApA".
I have created the following, which works... somewhat. "n" being the int.
int i = 0;
while(i <= n)
{
System.out.println(str.substring(0, Math.min(str.length(), n)));
n = n - 1;
i++;
}
This works for ints <= 2; if I input a string like "Chocolate" and the int 3, I will get "ChoCh" when I should be getting "ChoChC".
This has had me stumped for about 30 minutes. Any insight is appreciated.
Get rid of the i variable. You need to run the loop until the substring's length is 1, so:
while (n > 0)
{
System.out.println(str.substring(0, Math.min(str.length(), n)));
n = n - 1; // n-- would do the same thing here
}
Since you both increment i and decrement n, your loop only happens roughly n/2 times. This might have been clearer to you if you had tried in a debugger with a larger value of n, obviously paying particular attention to the loop condition.
If I have a string and an int, I want to be able to create a loop that will print the first char of the string, followed by each the char at value of that int.
e.g. If I have the word "Miracle" and the int 2, the result should be "Mrce". My code does this, but stops a char short for certain words.
System.out.println(str.charAt(0));
while (n <= str.length())
{
System.out.println(str.charAt(n));
n = n+n;
}
This works for strings like "abcdefg" and int 3. It prints "adg", but if the string is "miracle" and int 2, it prints "mrc" and not "mrce".
I'm pretty sure the problem is in the "n= n+n" statement.
Because if the int is 3 and the string is greater than 3 it will loop, but in the n=n+n statement it will loop enough that n will be greater than str length and it halts.
How can I correct this?
You are right, your problem is with n=n+n because it multiple n with 2 in every step so you must change that.
change your code like this :
int m = 0;
while (m < str.length())
{
System.out.println(str.charAt(m));
m = m+n;
}
n = n+n; means that in each iteration you are multiplying your n by 2, so
iteration | n
----------+-------
1 | 3
2 | 3+3=6
3 | 6+6=12
and so on.
What you need is temporary variable (iterator) which will use n but will not change it.
Generally more readable way to write it would be with for loop like
for (int i = 0; i < str.length(); i = i+n){//or `i += n`
^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^
// start at continue when in next step
System.out.print(str.charAt(i));
}
I'll answer with a counterquestion: where is this mentionned int? What walue should it have, and what value does it have?
In short, you should have one variable which has the step value and another variable which acts as a cursor.
Something like
int cursor = 0;
while (cursor <= str.length()) {
System.out.println(str.charAt(cursor));
cursor += stepValue;
}
Here you see that it is necessary to have two distinct variables here.
It is working for first few instances as 2+ 2 = 4, but after that - its doing 4 + 4 = 8, while you need is 4 + 2 = 6.
Take a new var (v), assign it the initial value, & instead of doing n = n + n, do
n = n + v
I think this is what you need
int n = 0;
int skip = 2;
while (n < str.length())
{
System.out.println(str.charAt(n));
n+=skip;
}
First of all, you have an error here:
n <= str.length()
It should be
n < str.length()
because strings are indexed from 0 to length-1.
Also make sure you are indexing from 0, not from 1.
Another thing is that you are adding a bigger number each time. So yes - you are right about n+n - it's wrong.
You should do something like this:
n = ...;
for (int i = 0; n * i < str.length(); ++i)
{
int index = n * i;
System.out.println(str.charAt());
}
This way you have n * 0, n * 1, n * 2, ..., which is what you want.
There are two things wrong in your code:
If n == str.length(), it will throw an exception, as it tries to
access str.charAt(n), which in that case doesn't exist.
Another thing, n = n + n will change the value of n every time, so you
will add a bigger number every time instead of the same.
You could use a for-loop for a cleaner approach though:
for (int i = 0; i < str.length(); i += n) {
System.out.println(str.charAt(i));
}
static int sumAfterPos(int[] A) {
int N = A.length;
for (int i = 0; i < N; i += 1) {
if (A[i] > 0) {
int S;
S = 0;
for (int j = i + 1; j < N; j += 1) {
S += A[j];
}
return S;
}
}
return 0;
}
I am having trouble figuring out whether this code runs in O(n^2) or in O(n). I am not sure whether the return S will have a big impact on the runtime.
It is O(N) in time.
For example, A[K] > 0, then you have already have K steps. Then you run another N-K steps and return. So totally you have O(N).
Let us say, all A[i] < 0, this will make the inner loop away. So it is O(N) in this case.
Now let us say, A[0] > 0, this will make the out loop only repeat once and the inner loop will run from 1 to N - 1, so totally you have 1 + (N-1 - 1 + 1) = N.
Now let us say, A[1] > 0, this will make the out loop only repeat twice and the inner loop will run from 2 to N - 1, so totally you have 2 + (N-1 - 2 + 1) = N.
...
Now let us say, A[k] > 0, this will make the out loop only repeat k + 1 times and the inner loop will run from k + 1 to N - 1, so totally you have k + 1 + (N-1 - k -1 + 1) = N.
Now let us say, A[N-1] > 0, this will make the out loop only repeat N and the inner loop will never run, so totally you have N times.
This looks to be O(n), or rather, exactly N iterations will occur. If the statement (A[i] > 0) is true, then a value would be returned after the inner for loop completes its iterations. If there are N elements in the array A, and the outer for loop is at iteration i, and the conditional is met, then the inner for loop will iterate at most N-i times and then return. If the conditional is never met, then the outer for loop will iterate N times. Thus, exactly N iterations between the outer- and inner- for loops will execute.
Return statements are generally never taken into account in determining the runtime complexity of an algorithm (unless the return statement for some reason is non-trivially complex (eg recursion)).
EDIT: For another perspective, note that as the index i increases linearly, the starting point for the index j increases linearly at the same rate, and thus the possible remaining work is decreasing linearly at the same rate as well. Since the the function is guaranteed to return once the inner loop is reached, the total number of iterations between the two for loops is i+j=N by the end of execution.
I'm studying for a test and found this question:
I can't really determine the complexity, I figured it's either O(n2) or O(n3) and I'm leaning towards O(n3).
Can someone tell me what it is and why?
My idea that it's O(n2) is because in the j loop, j = i which gives a triangle shape, and then the k loop goes from i + 1 to j, which I think is the other half of the triangle.
public static int what(int[] arr)
{
int m = arr[0];
for (int i=0; i<arr.length; i++)
{
for (int j=i; j<arr.length;j++)
{
int s = arr[i];
for (int k=i+1; k<=j; k++)
s += arr[k];
if (s > m)
m = s;
}
}
return m;
}
Also if you can tell me what it does?
I figured it returns the addition of positive integers or the biggest integer in the array.
But for arrays like {99, -3, 0, 1} it returns 99, which I think is because it's buggy. If not than I have no Idea what it does:
{99, 1} => returns 100
{-1, -2, -3} => return -1
{-1, 5, -2} => returns 5
{99, -3, 0, 1} => returns 99 ???
You can proceed methodically, using Sigma Notation, to obtain the order of growth complexity:
You have 3 for statements. For large n, it is quite obvious that is O(n^3). i and j have O(n) each, k is a little shorter, but still O(n).
The algorithm returns the biggest sum of consecutive terms. That's why for the last one it returns 99, even if you have 0 and 1, you also have -3 that will drop your sum to a maximum 97.
PS: Triangle shape means 1 + 2 + ... + n = n(n+1) / 2 = O(n^2)
Code:
for (int i=0; i<arr.length; i++) // Loop A
{
for (int j=i; j<arr.length;j++) // Loop B
{
for (int k=i+1; k<=j; k++) // Loop C
{
// ..
}
}
}
Asymptotic Analysis on Big-O:
Loop A: Time = 1 + 1 + 1 + .. 1 (n times) = n
Loop B+C: Time = 1 + 2 + 3 + .. + m = m(m+1)/2
Time = SUM { m(m+1)/2 | m in (n,0] }
Time < n * (n(n+1)/2) = 1/2 n^2 * (n+1) = 1/2 n^3 + 1/2 n^2
Time ~ O(n^3)
No matter triangle shape or not, it always a complexity O(N^3), but of course with lower constant then a full triple nested cycles.
You can model the running time of the function as
sum(sum(sum(Theta(1), k=i+1..j),j=i..n),i=1..n)
As
sum(sum(sum(1, k=i+1..j),j=i..n),i=1..n) = 1/6 n^3 - 1/6 n,
the running time is Theta(n^3).
If you do not feel well-versed enough in the underlying theory to directly apply #MohamedEnnahdiElIdri's analysis, why not simply start by testing the code?
Note first that the loop boundaries only depend on the array's length, not its content, so regarding the time complexity, it does not matter what the algorithm does. You might as well analyse the time complexity of
public static long countwhat(int length) {
long count = 0;
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++) {
for (int k = i + 1; k <= j; k++) {
count++;
}
}
}
return count;
}
Looking at this, is it easier to derive a hypothesis? If not, simply test whether the return value is proportional to length squared or length cubed...
public static void main(String[] args) {
for (int l = 1; l <= 10000; l *= 2) {
long count = countwhat(l);
System.out.println("i=" + l + ", #iterations:" + count +
", #it/n²:" + (double) count / l / l +
", #it/n³:" + (double) count / l / l / l);
}
}
... and notice how one value does not approach anyconstant with rising l and the other one does (not incidentally the very same constant associated with the highest power of $n$ in the methodological analysis).
This requires O(n^3) time due to the fact that in the three loops, three distinct variables are incremented. That is, when one inside loop is over, it does not affect the outer loop. The outer loop runs as many times it was to run before the inner loop was entered.
And this is the maximum contiguous subarray sum problem. Self-explanatory when you see the example:
{99, 1} => returns 100
{-1, -2, -3} => return -1
{-1, 5, -2} => returns 5
{99, -3, 0, 1} => returns 99
There is an excellent algorithm known as Kadane's algorithm (do google for it) which solves this in O(n) time.
Here it goes:
Initialize:
max_so_far = 0
max_ending_here = 0
Loop for each element of the array
(a) max_ending_here = max_ending_here + a[i]
(b) if(max_ending_here < 0)
max_ending_here = 0
(c) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
return max_so_far
References: 1, 2, 3.
O(n^3).
You have calculated any two item between arr[0] and arr[arr.length - 1], running by "i" and "j", which means C(n,2), that is n*(n + 1)/2 times calculation.
And the average step between each calculation running by "k" is (0 + arr.length)/2, so the total calculation times is C(n, 2) * arr.length / 2 = n * n *(n + 1) / 4, that is O(n^3).
The complete reasoning is as follows:
Let n be the length of the array.
1) There are three nested loops.
2) The innermost loop performs exactly j-i iterations (k running from i+1 to j inclusive). There is no premature exit from this loop.
3) The middle loop performs exactly n-j iterations (j running from i to n-1 inclusive), each involving j-i innermost iterations, in total (i-i)+(i+1-i)+(i+2-i)+... (n-1-i) = 0+1+2... + (n-1-i). There is no premature exit from this loop.
4) The outermost loop performs exactly n iterations (i running from 0 to n-1 inclusive), each involving 0+1+2+ ... (n-1-i) innermost iterations. In total, (0+1+2... n-1) + (0+1+2+... n-2) + (0+1+2+... n-3) + ... (0). There is no premature exit from this loop.
Now how do handle handle this mess ? You need to know a little about the Faulhaber's formula (http://en.wikipedia.org/wiki/Faulhaber%27s_formula). In a nutshell, it says that the sum of integers up to n is O(n^2); and the sum of the sum of integers up to n is O(n^3), and so on.
If you recall from calculus, the primitive of X is X^2/2; and the primitive of X^2 is X^3/3. Every time the degree increases. This is not by coincidence.
Your code runs in O(n^3).