This is my first stack overflow post so sorry if its not in the right format. In any case, the following is in C# and I'm using Visual Studio 2019 .NET Core 3.1
Goal: Sorting an Array of integers in ascending order ex. [3, 2, 5, 1] -> [1, 2, 3, 5]
Problem: Method sorts everything but the first element ex. [3, 2, 5, 1] -> [3, 1, 2, 5]
Code:
for (int i = 0; i < array.Length; i++)
{
if(i != array.Length - 1 && array[i] > array[i + 1])
{
int lowerValue = array[i + 1];
int higherValue = array[i];
array[i] = lowerValue;
array[i + 1] = higherValue;
i = 0;
}
}
I've put in Console.WriteLine() statements(one outside of the for loop above to see the starting array and one in the if statement to see how it updates the array when a change happens and yes I know I could use the debugger, but I don't currently have any method calls to the method this for loop is in) to see how its adjusting the array as it goes along and it will regularly show that its running through an iteration without changing anything.
Also if anyone could tell me what the time complexity of this is, that would be great. My initial guess is that its linear but I feel like with the "i = 0" statement and the way it swaps values makes it exponential. Thanks!
When I run your code, I get 2135
As #Flydog57 says, it would be useful to go through every single step to notice when it doesn't run as desired. The code looks a bit like a BubbleSort without inner loop... The iteration also goes through only once. If I see it correctly, you are missing a multiple iteration. Have a look at the BubleSort.
My suggestion for the sorting looks like this:
int[] array = { 3, 2, 5, 1 };
var sortedArray = array.OrderBy(p => p).ToArray();
Regarding O notation, I am unfortunately a bit rusty and can't help. But for me it looks like O(n).
Your algorithm is not a variant of bubble sort and it reset the loop counter when facing to descending order. in Bubble sort in every traverse, we are sure that the global max/min is in the right place but your algorithm is not sure about that till the execution for the last i.
In your algorithm, the left part of the array is always partially ordered.
Firstly, the problem with your code is that after resetting the counter, the loop would add it up to 1(i++), therefore in your code, it can't be less than 1. if you set it to -1 it would sort the array, because after setting it to -1 the loop changes it to 0 and that's the desired behavior. The if block should be like this:
if(i != array.Length - 1 && array[i] > array[i + 1])
{
int lowerValue = array[i + 1];
int higherValue = array[i];
array[i] = lowerValue;
array[i + 1] = higherValue;
i = -1;
}
The order of the algorithm: The worst-case happens when the array is in descending order, and in this case, for every i, The if condition would be true then the i would be reset to zero, therefore the total time complexity would be:
1 + 2 + 3 + 4 + .. + n(array length)= n(n+1)/2= O(n^2)
Related
This question already has answers here:
How to sort a list so that the same changes would happen in another list?
(3 answers)
Closed 3 months ago.
I have a question:
For example I had a list with 132 and a second list 123
I would want my 132 list.sort but the 123 list to sort like 132:
was:
132
123
After
123
132
Not switch place but if the first element changes position in list 1 so should list 2, please help.
This answer involves writing (or editing an existing) sorting algorithm.
In the example below, I've illustrated a way in Javascript to enhance a simple Bubble Sort algorithm to include a second array to manipulate aswell.
I know the question is for C#, but the same concepts apply.
The arrays need to have the same length, otherwise you will get errors.
// Bubblesort algorithm stolen from https://www.geeksforgeeks.org/bubble-sort/
// edited to include a second array (arr2) that mirrors the sorting of the first array
function swap(arr, xp, yp)
{
var temp = arr[xp];
arr[xp] = arr[yp];
arr[yp] = temp;
}
function bubbleSort( arr, arr2, n)
{
var i, j;
for (i = 0; i < n-1; i++)
{
for (j = 0; j < n-i-1; j++)
{
if (arr[j] > arr[j+1])
{
swap(arr,j,j+1);
// swap the elements of the second array aswell
swap(arr2,j,j+1);
}
}
}
}
// just a function for printing
function printArray(arr, size)
{
var i;
for (i=0; i < size; i++)
document.write(arr[i]+ " ");
document.write("<br />");
}
// the two arrays
var array1 = [5, 1, 4, 2, 8];
var array2 = [2, 3, 4, 5, 6];
var n = 5;
document.write("UnSorted arrays: <br />");
printArray(array1, n);
printArray(array2, n);
bubbleSort(array1, array2, n);
document.write("Sorted arrays: <br />");
printArray(array1, n);
printArray(array2, n);
If you run the above snippet, you see that the '1' in the second position of the first array has moved to the first position.
The second array had a '3' in the second position, which is also swapped to the first position, like the first array did.
Long story short: The second array mirrors the sorting of the first array.
everyone. I've this small task to do:
There are two sequences of numbers:
A[0], A[1], ... , A[n].
B[0], B[1], ... , B[m].
Do the following operations with the sequence A:
Remove the items whose indices are divisible by B[0].
In the items remained, remove those whose indices are divisible by B[1].
Repeat this process up to B[m].
Output the items finally remained.
Input is like this: (where -1 is delimiter for two sequences A and B)
1 2 4 3 6 5 -1 2 -1
Here goes my code (explanation done via comments):
List<int> result = new List<int>(); // list for sequence A
List<int> values = new List<int>(); // list for holding value to remove
var input = Console.ReadLine().Split().Select(int.Parse).ToArray();
var len = Array.IndexOf(input, -1); // getting index of the first -1 (delimiter)
result = input.ToList(); // converting input array to List
result.RemoveRange(len, input.Length - len); // and deleting everything beyond first delimiter (including it)
for (var i = len + 1; i < input.Length - 1; i++) // for the number of elements in the sequence B
{
for (var j = 0; j < result.Count; j++) // going through all elmnts in sequence A
{
if (j % input[i] == 0) // if index is divisible by B[i]
{
values.Add(result[j]); // adding associated value to List<int> values
}
}
foreach (var value in values) // after all elements in sequence A have been looked upon, now deleting those who apply to criteria
{
result.Remove(value);
}
}
But the problem is that I'm only passing 5/11 tests cases. The 25% is 'Wrong result' and the rest 25% - 'Timed out'. I understand that my code is probably very badly written, but I really can't get to understand how to improve it.
So, if someone more experienced could explain (clarify) next points to me it would be very cool:
1. Am I doing parsing from the console input right? I feel like it could be done in a more elegant/efficient way.
2. Is my logic of getting value which apply to criteria and then storing them for later deleting is efficient in terms of performance? Or is there any other way to do it?
3. Why is this code not passing all test-cases or how would you change it in order to pass all of them?
I'm writing the answer once again, since I have misunderstood the problem completely. So undoubtly the problem in your code is a removal of elements. Let's try to avoid that. Let's try to make a new array C, where you can store all the correct numbers that should be left in the A array after each removal. So if index id is not divisible by B[i], you should add A[id] to the array C. Then, after checking all the indices with the B[i] value, you should replace the array A with the array C and do the same for B[i + 1]. Repeat until you reach the end of the array B.
The algorithm:
1. For each value in B:
2. For each id from 1 to length(A):
3. If id % value != 0, add A[id] to C
4. A = C
5. Return A.
EDIT: Be sure to make a new array C for each iteration of the 1. loop (or clear C after replacing A with it)
I'm running this code, but every time, I get the error "An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred" on the first line of the for loop. Its basically code for a multiple choice quiz question, with questions & answers stored in a 2d array.
Unfortunately, I can't seem to spot the problem. It's probably a simple error, but I'm a beginner so I'm struggling to spot it.
I've read through similar questions, but I don't understand why this line is causing problems. I've got 4 elements in my list, one is removed before the loop, so there should be 3 left. I'm only looping through 3 times, so I don't understand what the problem is.
Hopefully someone will be able to help, Thanks!
Random rndq = new Random();
Random rnda = new Random();
List<int> answers = new List<int> { 1, 2, 3, 4 };
int questionchoice = rndq.Next(0, questions.GetLength(0) - 1);
int labelchoice = rnda.Next(0, answers.Count-1);
lblQuestion.Text = questions[questionchoice, 0];
var answer = (Label)Controls["lblAns" + answers[labelchoice]];
answer.Text = questions[questionchoice, 1];
answers.Remove(labelchoice);
int j = 2;
for (int i = 0; i < 3; i++)
{
var wronganswers = (Label)Controls["lblAns" + answers[i]];
wronganswers.Text = questions[questionchoice, j];
answers.RemoveAt(i);
j++;
}
Each pass through the loop you're removing an item from the list. After the first pass your list has 3 items in it [2, 3, 4]. Next pass there are two items left [2, 4]. Then you try to get the third item from the list of two and get an exception.
Either you need to leave the list alone while looping or make sure that your loop condition actually references the length of the list. Assuming that you want to actually process all 4 items I would suggest that you remove the RemoveAt call completely.
Or if you actually want to remove the items, reverse the direction of your loop:
for (int i = answers.Count - 1; i >= 0; i--)
{
// ....
answers.RemoveAt(i);
}
This will still process all of the items in the list and leave you with nothing in the list at the end.
I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}
I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();
I am trying to make a C# for loop that will loop through an array of items and print the first date of the user. Below is the code for the array (which i think is correct).
string[,] arrHolidays = new string[2, 3];
arrHolidays[0, 0] = "10/05/2015";
arrHolidays[0, 1] = "15/05/2015";
arrHolidays[0, 2] = "Danny";
arrHolidays[1, 0] = "20/05/2015";
arrHolidays[1, 1] = "22/05/2015";
arrHolidays[1, 2] = "Kieran";
Below is the code for the For loop (which is throwing the error)
for(int i = 0; i < arrHolidays.Length; i++)
{
Console.WriteLine(arrHolidays[i, 0]);
}
Index out of range exception was unhandled. this is the error I am recieving. When it throws the error and I check the value of 1 it is 2 if this is any help in resolving it.
What I am expecting to see is this in the console app:
10/05/2015
20/05/2015
INB4 I have hardly any c# experience this is my first project, so please explain any help :)
You must use GetLength method, not the Length property.
The Length property for a multi-dimensional array returns the total count of all the items in the array. The GetLength method returns the number of size of a given dimension (where dimension is specified as a zero-based index).
So, arrHolidays.Length will return 6.
Change for loop to:
for (int i = 0; i < arrHolidays.GetLength(0); i++)
{
Console.WriteLine(arrHolidays[i, 0]);
}
Array.GetLength(int dimension)
In your case, you want to get the length of the first dimension, so arrHolidays.GetLength(0).