Next in my series of Big O questions that I can't find the answer to
Take the following example
for(int i = 0; i < someNumber; i++)
{
for(int j = i; j < someNumber; j++)
{
DoSomething();
}
}
Would this still be considered O(n^2)? I only ask because I feel that this has to be less that O(n^2), since the inner loop is executing less and less for every iteration of i (since j is starting closer and closer to someNumber).
Thanks
The outer loop runs n times. The inner loop starts out running n times, but decreases with each iteration of the outer loop, until the last iteration where it only runs once. The code inside the inner loop will run
n + (n−1) + ... + 2 + 1
times.
That can be simplified to n(n + 1)/2 (proof), or n2/2 + n/2, or finally (n2 + n) / 2. Since the first term is n2, the algorithm is in O(n2).
Related
First time asking a question on Stackoverflow, fingers crossed! I'm new to programming and I'm struggeling to solve an issue. I got this foor loop:
for (int i = 0; i < antal.Count(); i++)
{
tbxResultat.AppendText(namnLista.ElementAt(i) + " \t");
tbxResultat.AppendText(personnummerLista.ElementAt(i).ToString() + " \t");
tbxResultat.AppendText(distriktLista.ElementAt(i) + " \t");
tbxResultat.AppendText(antal.ElementAt(i).ToString() + newLine);
}
I want to group the results from the loop into 4 sections: first values 0-49, second 50-99, third 100-199 and fourth 199. I'm interested in seeing how many is in each section and having it printed right each section, like:
23
37
---------------------------------
Total count of 2 in first section.
I've tried putting the for-loop in if statments but with no success. The sortment of the list is done with bubble sort which i modified to take a List instead of array. Any tips in the right direction would be much appriciated!
/Drone
This code should be what you asked for. Note the while in there. It's not if because there may be groups with zero elements, so you have to handle those as well.
int groupLimit = 50;
int elementsInGroup = 0;
for (int i = 0; i < antal.Count(); i++, elementsInGroup++)
{
while (antal[i] >= groupLimit)
{
// Write summary here. Use elementsInGroup..
groupLimit += 50;
elementsInGroup = 0;
}
// Write one row here. I suggest building the string and calling only one AppendText..
}
In a course a problem was to list the first n primes. Apparently we should implement trial division while saving primes in an array to reduce the number of divisions required. Initially I misunderstood, but got a working if slower solution using a separate function to test for primality but I would like to implement it the way I should have done.
Below is my attempt, with irrelevant code removed, such as the input test.
using System;
namespace PrimeNumbers
{
class MainClass
{
public static void Main (string[] args)
{
Console.Write("How many primes?\n");
string s = Console.ReadLine();
uint N;
UInt32.TryParse(s, out N)
uint[] PrimeTable = new uint[N];
PrimeTable[0] = 2;
for (uint i=1; i < N; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i -1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for(uint k=0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
break;
}
}
j++;//j increment mentioned above
}
PrimeTable[i] = j; //not different if this is enclosed in brace above
}
for (uint i = 0; i < N; i++)
Console.Write(PrimeTable[i] + " ");
Console.ReadLine();
}
}
}
My comments are my attempt to describe what I think the code is doing, I have tried very many small changes, often they would lead to divide by zero errors when running so I added in a test, but I don't think it should be necessary. (I also got several out of range errors when trying to change the loop conditions.)
I have looked at several questions on stack exchange, in particular:
Program to find prime numbers
The first answer uses a different method, the second is close to what I want, but the exact thing is in this comment from Nick Larsson:
You could make this faster by keeping track of the primes and only
trying to divide by those.
C# is not shown on here: http://rosettacode.org/wiki/Sequence_of_primes_by_Trial_Division#Python
I have seen plenty of other methods and algorithms, such as Eratosthenes sieve and GNF, but really only want to implement it this way, as I think my problem is with the program logic and I don't understand why it doesn't work. Thanks
The following should solve your problem:
for (uint i = 1; i < numberOfPrimes; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i - 1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for (uint k = 0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
j++;
break;
}
}
}
PrimeTable[i] = j;
}
The major change that I did was move the incrementation of the variable j to inside the conditional prime check. This is because, the current value is not prime, so we want to check the next prime number and must move to the next candidate before breaking in the loop.
Your code was incrementing after the check was made. Which means that when you found a prime candidate, you would increment to the next candidate and assign that as your prime. For example, when j = 3, it would pass the condition, isPrime would still = true, but then j++ would increment it to 4 and that would add it to the PrimeTable.
Make sense?
This might not be a very good answer to your question, but you might want to look at this implementation and see if you can spot where yours differs.
int primesCount = 10;
List<uint> primes = new List<uint>() { 2u };
for (uint n = 3u;; n += 2u)
{
if (primes.TakeWhile(u => u * u <= n).All(u => n % u != 0))
{
primes.Add(n);
}
if (primes.Count() >= primesCount)
{
break;
}
}
This correctly and efficiently computes the first primesCount primes.
I wrote code to implement a bidirectional selection sort in parallel. I used c#, and the the parallel.invoke function. 2 loops were invoked in parallel, one to find the minimum, and one to find the max. Yet, it doesn't sort. I was wondering is the problem because this type of sort can't handle being done in parallel, since each loop relies on data existing in the other loop?...or is there simply something wrong with my code?
Parallel.Invoke(
() =>
{
for (int i=0; i < array.Length / 2; i++)
{
int m;
int min = i;
for (m = i + 1; m < array.Length - 1; m++)
if (array[m] < array[min])
min = m;
//swap
int temp = array[min];
array[min] = array[m];
array[m] = temp;
}
},
() =>
{
for (int m = 0; m < array.Length / 2; m++)
{
int length = array.Length - 1;
int max = length - m;
int k;
for (k = length--; k > 0; k--)
if (array[k] > array[max])
max = k;
//swap
int temp = array[max];
array[max] = array[k];
array[k] = temp;
}
});
I think it's easier if you search the minimum and maximum within the same loop in 1 thread: (java-code, but I assume you'll understand the principle)
int minimum, maximum;
int k = size();
for(int i = 0; i < size(); ++i)
{
--k;
minimum = i;
maximum = k;
if(k - i <= 0)
break;
for(int j = i; j <= k; ++j)
{
if(greaterThan(minimum, j))
minimum = j;
if(lessThan(maximum, j))
maximum = j;
}
if(minimum != i)
{
swap(minimum, i);
if(maximum == i)
maximum = minimum;
}
if(maximum != k)
swap(maximum, k);
}
The problem with your code is this:
Say this is the array:
[5, 4, 3, 2, 1]
Iteration 0: The first thread will find the smallest element to put on index 0
The first thread finds the minimum element at index 4
Iteration 0: The second thread will find the largest element to put on index 4
The second thread finds the maximum element at index 0
You will already see that this will not end well, as both threads will perform a swap between index 0 and 4 resulting in the same situation as it is now.
Another problem is if your first thread is looping from m -> array.length - 1. If at the same time thread 2 moves the minimum element (which it doesn't need, because it's searching the maximum) from index k to "max" via a swap. With index "max" being < "m". That means the first thread will never find the next minimum value because it was moved before its position.
EDIT: After consideration, I don't think it's possible to implement a straightforward parallel version of selection sort. The version I first recommended was indeed not going to work due to the algorithm finding the same minimum every time because it didn't change the input-array.
What is possible is to only perform selection sort with thread 1 on the first half of the array (and only allow it to find the minimum in that half) and the second half of the array is for the second thread. And then in the end you can merge both halfs with a mergesort-algorithm.
This way you can always use more than 2 threads; say "p" amount of threads for example. Each responsible for N/p part of the input array with "N" being the inputsize. And in the end you just merge every part with a mergesort-algorithm. I never implemented it myself, so I can't say if it would be efficient, but I assume there will be better algorithms to parallelize out there (like mergesort itself).
PS: About the code posted above. I assume everything seems rather straightforward except this part:
if(maximum == i)
maximum = minimum;
That's to deal with a situation like this:
. . . i . . . k
[1, 4, 3, 1, 5]
so with i = 1 and k = 3 (the indices).
The algorithm will find:
maximum = index 1
minimum = index 3
After swapping the minimum value with the one on index i, the situation changes like this:
. . . i . . . k
[1, 1, 3, 4, 5]
Meaning the maximum value (integer 4) actually moved from index "i" to index "minimum". If we would perform a swap(maximum, k), it would have a bad result. That's why we need to update the index of the maximum element if it was positioned at index i.
I have a homework assignment of coding a bidirectional bubble sort. Can someone please see if my logic is correct with respect to it. I Don't want code as I want to figure it out myself. I just want a logic check of how i understand it.
As i understand the Bidirectional Bubble sort you implement 2 for loops one starting at position 1 in the list and performing a normal bubble sort. As the first for loop reaches the end a second one is implemented working in reverse. I just don't completely understand what the terminating conditions for each loop would be.
Would the for loop conditions be something as follows?
loop 1 - for(i = 0; i < Count -i; i++)
loop 2 - for(j = Count - i; j > i; j--)
in each loop the swap conditions would be specified.
Thanks
The "classic" bubble sort goes through the entire array on each iteration, so the loops should be
for(i = 0; i < Count - 1; i++)
and
for(j = Count - 1; j > 0; j--)
Both loops skip one index: the first loop skips the last index, while the second loop skips the initial one. This is so that your code could safely compare data[i] to data[i+1], and data[j] to data[j-1].
EDIT The "optimized" bubble sort skips the initial k elements on k-th iteration. Since your bubble sort is bidirectional, you will be able to skip the initial k and the tail k elements, like this:
int k = 0;
do { // The outer loop
...
for(int i = k; i < Count - k - 1; i++)
...
for(int j = Count - k - 1; j > k ; j--)
...
k++;
} while (<there were swaps>);
bidirectional bubble sort works like this:
instead of passing the list from bottom to top every time (bubble sort) you start one time at the bottom and every second time from the top of the list.
the wikipedia article does a way better job at explaining it:
http://en.wikipedia.org/wiki/Cocktail_sort
- rich
Good morning, afternoon or night,
Up until today, I thought comparison was one of the basic processor instructions, and so that it was one of the fastest operations one can do in a computer... On the other hand I know multiplication in sometimes trickier and involves lots of bits operations. However, I was a little shocked to look at the results of the following code:
Stopwatch Test = new Stopwatch();
int a = 0;
int i = 0, j = 0, l = 0;
double c = 0, d = 0;
for (i = 0; i < 32; i++)
{
Test.Start();
for (j = Int32.MaxValue, l = 1; j != 0; j = -j + ((j < 0) ? -1 : 1), l = -l)
{
a = l * j;
}
Test.Stop();
Console.WriteLine("Product: {0}", Test.Elapsed.TotalMilliseconds);
c += Test.Elapsed.TotalMilliseconds;
Test.Reset();
Test.Start();
for (j = Int32.MaxValue, l = 1; j != 0; j = -j + ((j < 0) ? -1 : 1), l = -l)
{
a = (j < 0) ? -j : j;
}
Test.Stop();
Console.WriteLine("Comparison: {0}", Test.Elapsed.TotalMilliseconds);
d += Test.Elapsed.TotalMilliseconds;
Test.Reset();
}
Console.WriteLine("Product: {0}", c / 32);
Console.WriteLine("Comparison: {0}", d / 32);
Console.ReadKey();
}
Result:
Product: 8558.6
Comparison: 9799.7
Quick explanation: j is an ancillary alternate variable which goes like (...), 11, -10, 9, -8, 7, (...) until it reaches zero, l is a variable which stores j's sign, and a is the test variable, which I want always to be equal to the modulus of j. The goal of the test was to check whether it is faster to set a to this value using multiplication or the conditional operator.
Can anyone please comment on these results?
Thank you very much.
Your second test it's not a mere comparison, but an if statement.
That's probably translated in a JUMP/BRANCH instruction in CPU, involving branch prediction (with possible blocks of the pipeline) and then is likely slower than a simple multiplication (even if not so much).
It can often be very difficult to make such assertions about an optimising compiler. They do lots of tricks that make simple cases different from real code. That said, you aren't just doing a comparison, you're doing a compare/assign in a very tight loop. The thread you're working on may have to pause many times at the branch; the multiplication can assign as many times as it likes, as long as the last assignment is still last, so many multiplies can be going on at once.
As is the general rule, make your code clear and ignore minor timing issues unless they become a problem.
If you do have a speed problem a good tracing/timing tool will guide you much better than knowing if one operation is faster than other in a specific case.
I guess one comment I would make is that you are doing a lot more in the second operation:
a = (j < 0) ? -j : j;
Not only are you doing a comparison, but also effectivly a "if..else.." with the ? operator and a negation of j.
You should try to run this test a 1000 or so times and use avrage to compare you never now what CLR is doing in background