The problem is as follows:
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
My code:
public class Solution
{
public void Rotate(int[] nums, int k)
{
List<int> list = nums.ToList();
for (int i = 0; i < k; i ++)
{
int first = nums[0];
list.RemoveAt(0);
list.Add(first);
}
nums = list.ToArray();
}
}
And I got a wrong answer as follows:
Wrong Answer
Runtime: 156 ms
Your input
[1,2,3,4,5,6,7]
3
Output
[1,2,3,4,5,6,7]
Expected
[5,6,7,1,2,3,4]
My question:
I assign the adjusted list to nums but why it hasn't changed?
Objects in C# are reference types, but they're passed by value.
Imagine if I gave you a box. You're welcome to do whatever you want with the contents, and when I return to collect the box I keep whatever you've put in it.
However, if you decide to replace my box with a new box, and you put things in the new box, then I don't get those things when I come back to collect the original box I gave to you.
When you call
nums = list.ToArray();
you are discarding the nums that was passed to you and you are replacing it with something else. That replaced value does not leave the function. The leetcode script that called your function checks the original nums object (box) and finds its contents unchanged.
Try doing the following instead of the assignment expression I mentioned above:
for(int i=0; i<list.Count(); i++)
{
nums[i] = list[i];
}
Here you're modifying the contents of nums without changing the object.
I assign the adjusted list to nums but why it hasn't changed?
nums is a regular parameter, and as such is passed by value. Any changes you make to its handle (like assigning to it) won't be visible to the array passed in from the outside.
So either replace the items in the array given to you one by one, or pass the array parameter by reference (ref int[] nums).
As an aside, your solution is incredibly bad. You took what should have been a time-linear and memory-constant solution and made a time-quadratic monstrosity that allocates two entire needless arrays.
Related
I'm trying to program a Sudoku solver in C# in which I'm using a List of an integer array with all the positions of empty fields, because I need them in my algorithm.
In the progress of solving the Sudoku I need to remove those positions which got filled with a number. But somehow my list with empty positions does not get smaller, when I use the Remove-method.
I will explain my problem with a simplified example:
List<int[]> test1 = new List<int[]>();
test1.Add(new int[] { 0, 0 });
test1.Add(new int[] { 1, 7 });
test1.Remove(new int[] { 1, 7 });
The first line generates the list with my one dimensional integer array (which always consists of two values - one for the column and one for the row-number). The empty positions get added in a method, but in this example I just added them in these two lines.
Later on in my algorithm, I want to remove elements by using the Remove-function similarly to the Add-function. It throws no errors, even while compiling. However, it's not removing anything.
I tried using the RemoveAll-method, although I don't really understand, how it works and therefore didn't find a correct solution for my problem.
By trying out a List of integers (not an integer array) the Remove-method works perfectly, but in the case of an array it doesn't seem to work this way.
Even creating a seperat variable rem
int[] rem = new int[] { 1, 7 };
test1.Remove(rem);
does not work.
I'm a beginner so I don't really know if a List of arrays is the best solution in my case.
bool IntArrayPredicate(int[] element)
{
return element.SequenceEqual(new int[] { 2, 3 });
}
List<int[]> listOfIntArray = new List<int[]>();
listOfIntArray.Add(new int[] { 0, 0 });
listOfIntArray.Add(new int[] { 1, 7 });
listOfIntArray.Add(new int[] { 2, 3 });
listOfIntArray.RemoveAll(element => element.SequenceEqual(new int[] { 1, 7 })); //It Works!. Using lambda expresion. Remove by Comparing sequences that match equals.
int[] toRemove = listOfIntArray[0];
listOfIntArray.Remove(toRemove); //It works!. Remove element by exact reference.
listOfIntArray.Remove(new int[] { 2, 3 }); // Not working / References are different.
listOfIntArray.RemoveAll(IntArrayPredicate); // It works!. Same as using lambda but using method reference.
Console.WriteLine($"{nameof(listOfIntArray)} has {listOfIntArray.Count()} elements"); // Yup. 0 elements.
The reason you're not able to remove items from your list using the Remove method is that you're storing reference types in the List, but creating new references when trying to remove an item. Because reference types by default use a reference comparison (not a comparison of their fields) to determine equality, you won't be able to remove items in that way.
One way to resolve this is to create a reference to each object in the List<int[]> outside of the list creation itself. This way, you can use the existing reference as an argument to the Remove method, and, because it's referring to the same object that was added to the list, it will match and be removed:
// Here we have 'item1' and 'item2' that refer to the location of different int[]
int[] item1 = new int[] { 0, 0 };
int[] item2 = new int[] { 1, 7 };
// And now we use those references to add the int[] items to our list
List<int[]> test1 = new List<int[]>();
test1.Add(item1);
test1.Add(item2);
// Finally, we can remove an item using the same reference that we used to add it
test1.Remove(item2);
This is very clunky, however, since we now need to maintain an individual reference for every item in our list as well as the list itself.
Another way to resolve this would be to search for the item we want to remove using our own equality algorithm (rather than relying on the default equality that Remove uses). We can use FirstOrDefault to search for the first item that has a length of 2 and whose values match those that we want. It will return a reference to the item if it's found, or null if it's not found. We can use IndexOf to get the index of the item (or -1 if it's not found), and then pass that index to the RemoveAt method to remove it:
List<int[]> test1 = new List<int[]>();
test1.Add(new int[] { 0, 0 });
test1.Add(new int[] { 1, 7 });
int indexToRemove = test1.IndexOf(test1.FirstOrDefault(item =>
item.Length == 2 && item[0] == 1 && item[1] == 7));
if (indexToRemove >= 0) test1.RemoveAt(indexToRemove);
As you can see, what you're trying to do isn't super easy. As a suggestion to help you think about the problem in a different way, you might consider using a 2-dimensional array to store the sudoku grid. Normally we store the row in the first dimesion and the column in the second dimension:
int[,] grid = new int[9, 9];
You could potentially create a few of these, one to represent the puzzle solution, one to represent the puzzle shown to the user's (with just their guesses), maybe even one to store user's "notes" (if you allow them to tag a cell with possible values before committing to a guess), though that would likely need to be a string[,] or an int[,][].
Then the typical way to loop through the grid would be something like:
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
// Do something with the cell at 'row' 'col' here
// Set a value for this cell
grid[row, col] = row + col;
// Report the value of a cell
Console.WriteLine($"The value at row {row} and column {col} is {grid[row, col]}");
}
}
I am trying to update an array and add it to a list if a certain condition is true. As you can see in my code the array "rows" is updated every time inside the if condition, and the it is added to "checkList".
The problem is that when I iterate through the list to check the values, it seems that only the last value of rows has been added in every entry in the list.
Here is some code to explain
int[] rows = new int[2];
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
rows[0] = i;
rows[1] = j;
checkList.Add(rows);
}
}
}
foreach (var row in checkList)
{
Console.WriteLine(row[0] + " " + row[1]);
}
Output:
I hope someone can explain this. Thanks
Most object types in .NET (including arrays) are passed by reference, so checkList.Add(rows); adds a reference to the same array to the list, multiple times.
Instead, you'll want to create a new array instance every time:
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
checkList.Add(new int[]{ i, j });
}
}
}
I believe the issue here is that when you are
checkList.Add(rows);
You are adding a reference to the rows array every time to the list, not a separate copy of it. This leads to your current behaviour.
A solution would be to instantiate the array inside the loop, so a new array is created every iteration.
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
int[] rows = new int[2];
rows[0] = i;
rows[1] = j;
checkList.Add(rows);
}
}
}
As a supplement to Matthias answer, one of the things that's perhaps not easy to appreciate about C# is that most variables you have and use are merely a reference to something else. When you assign some variable like this:
int[] rows = new int[2];
C# creates some space in memory to keep an array of 2 integers, it attaches a reference to it, and that thing becomes your variable that you use, named rows. If you then do:
int[] rows2 = rows;
It doesn't clone the memory space used and create a new array, it just creates another reference attached to the same data in memory. If the data were a dog, it now has 2 leads attached to its collar but there is still only one dog. You can pull on either lead to urge the dog to stop peeing on a car, but it's the same dog you're affecting.
Array/list slots are just like variables in this regard. To say you have:
List<int[]> checkList = new List<int[]>();
Means declare a list where each of its slots are a variable capable of referring to an int array. It's conceptually no different to saying:
int[] checkList0 = row;
int[] checkList1 = row;
int[] checkList2 = row;
int[] checkList3 = row;
It's just that those numbers are baked into the name, whereas a list permits you a way of varying the name programmatically (and having more than 4 slots):
checkList[0] = row;
checkList[1] = row;
checkList[2] = row;
checkList[3] = row;
checkList[0] is conceptually the entire variable name, just like checkList0 is a variable name, and remember that this is hence just another variable that is just a reference to that same array in memory.
By not making a new array each time, you attached every variable slot in the list to the same array in memory, and thus you ended up with something in memory that looks like:
The black is the list, the blue is the array. Every list slot is just a reference to the same array. You might have changed the numbers in the array 200 times, but at the end of the oepration, because there was only ever one array, you only see the final set of numbers you wrote into the array. You might have attached 20 leads to your dog and pulled each of them once, but it's still just the same dog that has 20 times been stopped from peeing on 20 cars.
Matthias answer works (and is how it should be done) because you concretely make a new array each time
Numbers in blue are fabricated and not intended to represent the answers you should see printed; the concept being explained is that of linking to new array objects in memory
You'd be forgiven for thinking that a clone would be made, bcause it is for int. int is a value type, whcih means the value is copied when it's used:
int x = 1;
int y = x;
y = y + 1;
y is now 2, but x is still 1. It'd be pretty hard work to write C# if it wasn't this way i.e. if every time you incremented some int variable, every other variable that had touched the variable that it came from was also affected.. So I think it's perhaps intrinsically reasonable to assume that whenever an assignment of anything is made, changes that affect the value of the assigned variable don't affect earlier iterations of it.. but that's not the case. There's this clear divide between value types (types whose data is copied/cloned when they're assigned) and reference types (types whose data is not copied/cloned). While int is a value type (cloned), an int[] is a reference type (not cloned)
..and that's something you'll really need to get down with and remember
Roll on the what's ref/out for? query :D
I need to create a 2D array where size of column is fixed as 6 but size of row may vary . How to give dynamic row size in 2D array ?
Below is the code I tried but no luck.
int n;
string num = console.ReadLine();
Int32.TryParse(num,out n);
int[,] ar = new int[n,6] ;
There's nothing wrong with the way you're constructing the mulitidimentional array. The following code is valid so I suspect your error is somewhere else:
int n = 9;
int[,] ar = new int[n,6];
I'm guessing your input is not coming through correctly so add some error checks to figure out what went wrong. First, Console.ReadLine() has to be capitalized or it wont compile. Next, make sure TryParse is actually functioning properly (it returns a bool indicating success or failure:
int n;
string num = Console.ReadLine();
if (num == null) {
// ERROR, No lines available to read.
}
if (!Int32.TryParse(num,out n)) {
// ERROR, Could not parse num.
}
int[,] ar = new int[n,6];
If issues persist, people generally appreciate more descriptive explanations than "I tried but no luck." Make sure to inform people viewing your question that it was a compilation error or a runtime error and be as specific as you can.
I would use a Dictionary as so.
Dictionary<int,List<int>> numbers = new Dictionary<int,List<int>>();
And you could add an item like this:
numbers.Add(1,new List<int>(){1,2,3,4,5,6});
And to add numbers to a particular row.
numbers[1].Add(7);
And to access a number in a specific row and column.
numbers[1][2] = 34;
I would like to create a for loop to check if an index value has repeated, and if it has to remove it from the original and display an updated list with no repeated index values.
I have and Array (called Original) with multiple values being repeated, and then I created a Temporary Array (called TempArray) with the same exact values.
I want to check the Original and TempArray values against each other to see if there are duplicates.
I want my code to be similar to a previous one I did where I deleted an index from the middle of my array, as follows
for (int i = 0; i < Original.Length; i++)
{
TempArray[i] = Original[i];
}
Original = new int[Original.Length - 1];
//Set index to delete
int DeleteIndex = 3;
//modify size of Orignial array and copy in array without deleted element index
for (int i = 0; i < TempArray.Length; i++)
{
if (i < DeleteIndex)
{
Original[i] = TempArray[i];
}
else if (i > DeleteIndex)
{
Original[i - 1] = TempArray[i];
}
}
P.S. Original[] is an array from a text file. Sorry if my explanation is hard to understand as I am new to computer programming.
Also is there any way to do this code without LINQ, I have to create using arrays only as its all thats been taught at school?
It took some time to understand what you want :)
to check if an index value has repeated, and if it has to remove it from the original and display an updated list with no repeated index values
It is shortly called distinct values. There is a LINQ method .Distinct():
Original = Original.Distinct().ToArray();
It will remove all repeated values.
where I deleted an index from the middle of my array
You can do this easier by converting to List, applying RemoveAt and back:
var list = new List<int>(Original);
list.RemoveAt(DeleteIndex);
Original = list.ToArray();
P.S. Assuming that you say "index" about the values in your array, it is pretty confusing. Array does not store indices - index is usually understood as a key of an array.
May be this will do the trick for you. I am assuming that you need to remove duplicate from your array
Original = Original.Distinct().ToArray();
Will Returns distinct elements from a sequence by using the default equality comparer to compare values.
Hello i have a problem with c# Arrays. I need a array to store some data in there...
My Code is that
double[] ATmittelMin;
ATmittelMin[zaehlMittel] = Gradient(x, xATmax, y, yATmax);
But the compiler says: not defined var
How can i define a double array without a fixed size ?
Thanks a lot!
Arrays are always fixed in size, and have to be defined like so:
double[] items1 = new double[10];
// This means array is double[3] and cannot be changed without redefining it.
double[] items2 = {1.23, 4.56, 7.89};
The List<T> class uses an array in the background and redefines it when it runs out of space:
List<double> items = new List<double>();
items.Add(1.23);
items.Add(4.56);
items.Add(7.89);
// This will give you a double[3] array with the items of the list.
double[] itemsArray = items.ToArray();
You can iterate through a List<T> just as you would an array:
foreach (double item in items)
{
Console.WriteLine(item);
}
// Note that the property is 'Count' rather than 'Length'
for (int i = 0; i < items.Count; i++)
{
Console.WriteLine(items[i]);
}
From what I see you did not declare the zaehlMittel variable. I guess this is what the compiler complains about.
Apart from that, even though you can of course determine the value of that variable programmatically, the moment you want to create an array its size must be known. This is the way arrays work.
In case you cannot do that easily, I suggest using some sort of dynamic datastructure, like a list or a set. Then, once all elements have been added, you are of course still free to create an array from that, as by that time you know the number of elements (even though there are convenience methods like toArray() that will even take care of that).
You have to instanciate the array before using it:
double[] ATmittelMin = new double[10];
ATmittelMin[zaehlMittel] = Gradient(x, xATmax, y, yATmax);
The obvious solution that springs to mind is to use a List:
List<double> ATmittelMin = new List<double>();
ATmittelMin.Add(Gradient(x, xATMax, y, yATMax);
But if you don't want to convert from a list to an array you can grow the array later:
double[] ATmittelMin = new double[10];
// Some code
int index = some_value;
if (index >= TmittelMin.Length)
{
Array.Resize(ATmittelMin, index+5); // So we're not constantly resizing the array
}
It's not ideal as you're doing a lot of the work that List is doing behind the scenes - probably a lot more efficiently than you can.