I have a quick question: I know that the complexity of both snippets is same. Yet, I want to know which one is comparatively better and why? This is the selection sort code:
This is what I wrote:
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
This is what my friend wrote:
for (int i = 0; i < n - 1; i++)
{
int iMin = i;
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
iMin = j;
}
int temp = a[i];
a[i] = a[iMin];
a[iMin] = temp;
}
}
Your code is slightly faster because you make swaps only when a[j] < a[i], whereas your friend's code is always making a swap. So, in most cases, your code will make less swaps.
The complexity of both codes are indeed the same, but your "constants" are smaller, so your code is faster.
Related
I'm having a problem with getting this code (from Rosetta Code) to work as part of a greater Windows Form Project:
It's a plain old insertion sort. Where it's going wrong is the bit involving the second for loop (The numbers generate just fine), in the sorting part of it. To me within a couple of iterations of the loop then j will be into negative figures and whilst other languages such as Javascript and Pascal don't seem to mind this...C# isn't happy.
private void button3_Click(object sender, EventArgs e)
{
int i, j, k;
int[] a = new int[12];
Random randomObject = new Random();
ClearOutputs(); // this is an event which just clears the
text
from the text boxes.
//Generate some random numbers
for (i = 0; i < a.Length; i++)
{
a[i] = randomObject.Next(1, 1000);
textBox1.AppendText(a[i].ToString() + "\n");
}
for (i = 1; i <= a.Length; i++)
{
k = a[i];
//*******************
for (j = i; j > 0 & k < a[j - 1]; j--)
{
a[j] = a[j - 1];
a[j] = k;
}
}
// ***************
//Display them...it never executes this part.
for (i = 0; i < a.Length; i++)
{
textBox2.AppendText(a[i].ToString() + "\n");
}
}
The longer term fix would be for me to understand the coding of the algorithm...and then fix it for myself, but if anyone could point me in the right direction...I've tried setting the 'for' loop at a higher initial value and yet still got the same "System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'" Any help would be greatly appreciated.
Following the provided Rosetta Code algorithm, you should change the second "for" block to:
for (i = 1; i < a.Length; i++)
{
k = a[i];
for (j = i - 1; j >= 0 && a[j] > k; j--)
{
a[j + 1] = a[j];
}
a[j + 1] = k;
}
I'm trying to write a gold prospecting program that takes an initial data map in the form of a 2D array which then produces a map with all the likely places for gold marked on it.
However, when calculating the average to determine whether or not to mark the point for prospecting, I get a "System.IndexOutOfRangeException" exception thrown at me and the program breaks. How would I go about fixing this? Thank you for any help in advance.
for (int i = 1; i < nRows; i++)
{
for (int j = 1; j < nCols - 1; j++)
{
//it is at the line below where the program breaks
double average = (data[i - 1, j] + data[i + 1, j] + data[i, j - 1] + data[i, j + 1]) / 4;
if (data[i, j] > average)
{
map[i, j] = "*";
}
}
}
You go out of borders of your 2-D array. So change this part of your code:
for (int i = 1; i < nRows; i++)
{
for (int j = 1; j < nCols - 1; j++)
to
for (int i = 1; i < nRows - 2; i++) // NOT from 0 to nRows - 1
{
for (int j = 1; j < nCols - 2; j++) // NOT from 0 to nCols - 1
so you omit the borders.
I have written a console application
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
{
input[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < T; i++)
{
int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
{
for (int k = 0; k < input[i]; k++)
{
Matrix[j, k] = Math.Abs(j - k);
sum += Matrix[j, k];
}
}
Console.WriteLine(sum);
}
When I gave input as
2
1
999999
It gave Out of memory exception. Can you please help.
Look at what you are allocating:
input[] is allocated as 2 elements (16 bytes) - no worries
But then you enter values: 1 and 999999 and in the first iteration of the loop attempt to allocate
Matrix[1,1] = 4 bytes - again no worries,
but the second time round you try to allocate
Matrix[999999, 999999]
which is 4 * 10e12 bytes and certainly beyond the capacity of your computer even with swap space on the disk.
I suspect that this is not what you really want to allocate (you'd never be able to fill or manipulate that many elements anyway...)
If you are merely trying to do the calculations as per your original code, there is not need to allocate or use the array, as you only ever store one value and immediately use that value and then never again.
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
input[i] = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < T; i++)
{
// int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
for (int k = 0; k < input[i]; k++)
{
//Matrix[j, k] = Math.Abs(j - k);
//sum += Matrix[j, k];
sum += Math.Abs(j - k);
}
Console.WriteLine(sum);
}
But now beware - a trillion sums is going to take forever to calculate - it won't bomb out, but you might like to take a vacation, get married and have kids before you can expect a result.
Of course instead of doing the full squared set of calculations, you can calculate the sum thus:
for (int i = 0; i < T; i++)
{
sum = 0;
for (int j = 1, term = 0; j < input[i]; j++)
{
term += j;
sum += term * 2;
}
Console.WriteLine(sum);
}
So now the calculation is O(n) instead of O(n^2)
And if you need to know what the value in Matrix[x,y] would have been, you can calculate it by the simple expression Math.Abs(x - y) thus there is no need to store that value.
enter code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testing_random
{
class Program
{
static void Main(string[] args)
{
int n = 4;
int[,] a = new int[n,n];//declaring the matrix
Random o = new Random();
a[0,0] = o.Next(n);
for (int i = 1; i < n; i++)//filling the first line
{
int d = 1;
while (d != 0)
{
a[i,0] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[i,0] == a[j,0])
d++;
}
}
for (int i = 1; i < n; i++)//filing the first column
{
int d = 1;
while (d != 0)
{
a[0, i] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[0, i] == a[0, j])
d++;
}
}
for (int k = 1; k < n; k++)//filling the rest of the matrix
for (int i = 1; i < n; i++)
{
int d = 1;
while (d != 0)
{
a[i, k] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[i, k] == a[j, k])
d++;
for (int j = 0; j < k; j++)
if (a[i, k] == a[i, j])
d++;
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
Console.Write("{0} ", a[i, j]);
Console.WriteLine();
}
Console.ReadLine();
}
}
}
The output should be a matrix of 4*4 where each column and each line contains each number once.
The problem is when i run the code, not every time i get an output, i think the problem is not every set of first line and column can give a matrix as required the i get into an unending loop.
what i want to do is limit the running time of the application to 100 ms per example,so if the matrix is not filled,the program restarts
What piece of code am i missing?
replace the while( d != 0 ) with a loop which counts up to a certain very large maximum number of iterations. (Try 1000, 100000, whatever.)
Are you trying to randomly insert numbers between 1-4 in the first line of the array? If so there is a much easier way to do it.
You can generate the 4 numbers to be inserted into the array and then just look through the first line of the array and set each value.
Random rnd = new Random();
var randomNumbers = Enumerable.Range(1, 4).OrderBy(i => rnd.Next()).ToArray();
for (int i = 0; i < n; i++)
{
a[i, 0] = randomNumbers[i];
}
why doesn't the element get swapped
public static void SwapArray(int[,] arr)
{
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(0); j++)
{
int temp = arr[i, j];
arr[i, j] = arr[j, i];
arr[j, i] = temp;
}
}
}
even if the parameter is without a ref modifier the array doesn't change.
a copy of the reference is passed as a parameter right?
There is an error in your algorithm. For every i and j, your loop swaps arr[i,j] and arr[j,i] twice.
For example arr[3,1] gets swapped with arr[1,3] once for i=3, j=1 and once for i=1, j=3. So the result is the original matrix. You should change the j-loop to
for (int j = 0; j < i; j++)
The second arr.GetLength(0) should be arr.GetLength(1). Because you want to use the 2nd dimension.
try this.
I have changed the second for loop.
u r actually swapping and again reswapping. so u stand where u were.
public static void SwapArray(int[,] arr)
{
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = i+1; j < arr.GetLength(0); j++)
{
int temp = arr[i, j];
arr[i, j] = arr[j, i];
arr[j, i] = temp;
}
}
}
a copy of the reference is passed as a parameter right?
Arrays are passed by reference.
SwapArray(ref int[,] arr)
Here you are passing a reference by reference (sorry, for tautology), this means, that you can even reassign a reference:
arr = new int [10,20];