Understanding Code in Java - java

public static void mystery2d(int[][] a) {
for (int r = 0; r < a.length; r++) {
for (int c = 0; c < a[0].length - 1; c++) {
if (a[r][c + 1] > a[r][c]) {
a[r][c] = a[r][c + 1];
}
}
}
}
If a two-dimensional array named numbers is initialized to store the following integers, what are its contents after the call shown?
int[][] numbers = {
{3, 4, 5, 6},
{4, 5, 6, 7},
{5, 6, 7, 8}
};
mystery2d(numbers);
I am really trying to understand code with 2D list but am having difficulties following along through the for loops. If someone could walk me through the steps or explain to me how it works that would be great thank you very much!
For example what would be a the values of the code bellow so I could have something to see if I could see the iterations of the loop better?
numbers[0][0] = ??
numbers[1][1] = ??
numbers[2][3] = ??

The code is to remove the smallest element in each row.
This is how it works.
In First row, it will check if 3<4? It is true. So, the a[0]=3 is replaced as a[0]=4 but a[1]=4 remains same. The same procedure happens till it reaches the end of each row. So the number in the last position at the end of every 'c'th iteration remains same.
Hence, the Output will be :
4566
5677
6788
So, the smallest element in each row. i.e. 3,4,5 in 1st, 2nd and 3rd row respectively is removed from array. I hope you got something!

First off, you should use i and j in your for loops rather than r and c, it is good practice. Your loop compares one number with the next number and changes the original to the new number if the new is greater than the original. So numbers[0][0] would be compared 3 ? 4 = 3 < 4 = so the 3 now becomes a 4. numbers[1][1] would be 5 ? 6 = 5 < 6 = 5 now becomes 6. And so on. Hope this helps.

Related

Method that fills the gap between an ArrayList in Java

I'm making a method called fillList. The method will require an arrayList in order to work and the output will be void.
What the method is supposed to do is to fill the gaps between the numbers of the List.
Example:
Input:
4 8 5 9
Output:
4 5 6 7 8 7 6 5 6 7 8 9
The code I have so far is this:
public static void fillList(ArrayList<Integer> List) {
for(int i = 0; i < List.size(); i++) {
if(List.get(i) < List.get(i+1) ) {
List.add(List.get(i+1));
} else if(List.get(i) > List.get(i+1)) {
List.add(List.get(i-1));
}
}
}
My idea was to add 1 to the value of the first element if the first element was less than the second element in the List. For example if the first element is 4 then the code would add a 5 to the list and stop once the number added was equal to one less than the second element. And basically do the opposite if the first element was more than the second element.
I don't know how to stop this loop until the numbers that are being added reach the second element of the list. I am not confident about my code as well I'm pretty sure I am making an error I'm not seeing.
Great question, I think you can learn alot by working this one out and really understanding every single line. I have made a litte illutration for you, to visualize the problem better. Hope this can help you. General tips:
variables are always lowercase by convention so write list instead of List
list.add(5) will add the number 5 to the end of your ArrayList. You can use list.add(4, 5) for example to insert the number 5 into the array position 4.
To update the list while iterating over its indices, you can use method List.add(int index, E element), which expects an index and a new element to insert.
While iterating, you need to compare two adjacent elements and insert a new one under the following conditions:
Left element is less than the right one and difference between them is greater than 1. A new element should be equal left + 1.
Left element is greater than the right one, and they differ more than by 1. A new element should be equal left - 1.
Also have a look at the nicely illustrated answer by #yezper. And as a general advice: draw before coding in order to understand the algorithm better.
That's how implementation might look like:
public static void fillList(List<Integer> list) {
for (int i = 0; i < list.size() - 1; i++) {
int left = list.get(i);
int right = list.get(i + 1);
if (left < right && left + 1 != right) {
list.add(i + 1, left + 1);
} else if (left > right && left - 1 != right) {
list.add(i + 1, left - 1);
}
}
}
main()
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>(List.of(4, 8, 5, 9));
fillList(list1);
System.out.println(list1);
}
Output:
[4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 9]

Generating an array of non-repeating integers

I'm trying to generate an array of 5 non-repeating integers in Java, but there are still repeats when I run it. Here's my code so far:
public int[] generateCode(){
code[0] = (int)Math.round(Math.random()*8+1); // initialize first number so it won't be compared against
for(int i=1; i<code.length; i++){
code[i] = (int)Math.round(Math.random()*8)+1;
for(int j=0; j<i; j++){
while(code[i]==code[j]){
code[i] = (int)Math.round(Math.random()*8)+1;
}
} // end inner for loop
} // end outer for loop
return code;
} // end generateCode method
Any help is very much appreciated!
So, your for-loop is checking for repeated characters, BUT each time you generate a new value (in the while-loop) you're not checking to see if the value exits before j.
There are a number of possible ways you might address this issue, I prefer ones which uses Collections.shuffle, but assuming that you can't use features like Arrays, Collections, List, Set or possibly even streams, we need to work with what we have, arrays.
Since you have a small range of acceptable values which need to fit into an even smaller range, a simple solution might be to generate a "master" list of allowed values and randomly select a value from the master list, tracking which values you've already picked.
Sounds more complicated then it actually is, for example...
public int[] generateCode() {
int[] masterValues = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] codes = new int[5];
Random rnd = new Random();
int index = 0;
while (index < codes.length) {
int lookupIndex = 0;
do {
lookupIndex = rnd.nextInt(masterValues.length);
} while (masterValues[lookupIndex] == 0);
codes[index] = masterValues[lookupIndex];
masterValues[lookupIndex] = 0;
index++;
}
return codes;
}
This creates a "master" list of values. It then randomly calculates a "lookup" index, checks to see if the value in the master list is 0 or not, if not, it assigns it to the next index in the codes array and sets the value in the master list to 0, otherwise it generates a new random index and tries again. This all repeats till it fills the codes array
So doing something like...
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
could print (because it's "random")...
[8, 1, 4, 7, 5]
[9, 6, 2, 1, 8]
[6, 5, 9, 4, 7]
[2, 5, 3, 1, 4]
There are much easier ways to do this. Using a Set<Integer> would be one. Here is another.
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8));
Collections.shuffle(list);
System.out.println(list.subList(0,5));
prints something like
[4, 5, 8, 2, 1]
As was pointed out to me, you may not be allowed to use or know about collections. But I would recommend you at least make a helper method to check for duplicates to reduce the clutter. Something like the following:
public boolean contains(int[] arr, int n) {
for (int v : arr) {
if (v == n) {
return true;
}
}
return false;
}
Then you can keep checking the current value to be false before you add it. Once it works it also lets you focus on other aspects of your code.

Can someone correct the way I understand this code because the output is different than what I think?

public class Test{
public static void main(String[] args){
int[] a = {3, 2, 5, 21}; // created an array with 4 elements
int b,c;
for (b=0; b<=2; b++)//for loop that will have 3 iterations
{
if (a[b] < a[b+1])
{
c=a[b];//this
a[b] = a[b+1];//is
a[b+1] = c;//swapping
}
}
for(b=0; b<4; b++)
{
System.out.println(a[b]);
}
}
}
This outputs :
3 5 21 2
What I got when I was writing it down:
3 5 21 21
Could someone tell me how to approach it in my thoughts?
Well if you really want to just trace out the program you could go through each iteration of that first for-loop by hand (the second loop just prints the contents of a).
Before the loop starts, a holds
{3, 2, 5, 21}
First iteration (b = 0):
a[0] is not less than a[1] so we do nothing.
Second iteration (b = 1):
a[1] is less than a[2], so we swap them. Now a holds
{3, 5, 2, 21}
Third iteration (b = 2):
a[2] is less than a[3], so we swap them. Now a holds
{3, 5, 21, 2}
which is what gets printed subsequently.
Well, the code always outputs the initial elements of a, possibly permuted. Thus your expectation can't possibly have been correct, since it lost 2 and made 21 appear twice.
Well you got lost at the 3rd iteration so I'll start there.
The array is {3, 5, 2, 21}.
b = 2
if (a[b] < a[b+1]) is equivalent to if (2 < 21), this is true, so...
c=a[b];//this -> c = 2
a[b] = a[b+1];//is -> a[2] = 21
a[b+1] = c;//swapping -> a[2+1] = 2
so now a[2] = 21 and a[3] = 2 and the final array is:
{3, 5, 21, 2}
Each time you run the full outer loop you will end up with the next smallest element at the end of the array. So as you're only running the loop once you end up with 2 (being the first smallest element) at the end of the array.
As others have mentioned, if you want to make this a complete sort then you need more iterations of the main loop to complete the sort (n-1, where n is the length of the array, so in this case you would need to run the loop 3 times).

Any O(n) algorithm for smoosh method?

I am trying to finish a smoosh() method which will takes an array of ints. On completion the array should still contains the same numbers but wherever the array had two or more consecutive duplicate numbers, they are replaced by one copy of the number. Hence,
after smoosh() is done, no two consecutive numbers in the array are the same.
Any unused elements at the end of the array are set to -1.
For example, if the input array is
[ 1 1 0 0 4 4 5 0 0 0 7 ]
it reads
[ 1 0 4 5 0 7 ]
after smoosh() completes.
The method signature is:
public static void smoosh(int[] ints)
I was able to do it like this:
for (int i=0; i<ints.length-1; i++) {
if (ints[i+1]==ints[i])
ints[i]=-1;
}
for (int i=0; i<ints.length-1; i++) {
if (ints[i]==-1) {
for (int j=i+1; j<ints.length; j++) {
if (ints[j]!=-1) {
//swap ints[j] and ints[i] and then break;
}
}
}
}
However, this will be O(n2) time (although almost in place).
I feel like there should be some O(n) in place method to do this but I can't figure out how.
Could anyone think of any O(n) in place algorithm? (Obviously if you make another array of the same size to help processing then you can get O(n) easily but that's not what I am looking for since that's not in place...)
thanks!
Basically, as follows. This O(n)-time, O(1)-space "algorithm" is actually Python code, since that's a very good language for teaching basic algorithms, as long as you avoid all the complex stuff, like lambdas.
I'm actually using it to teach my 8yo son at the moment as he's expressed an interest in what I do all day at work.
array = [1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]
print array
count = len (array)
last = array[0] - 1
toidx = 0
for fromidx in range (0, count):
if array[fromidx] != last:
array[toidx] = array[fromidx]
toidx = toidx + 1
last = array[fromidx]
while toidx < count:
array[toidx] = -1
toidx = toidx + 1
print array
The output of this is:
[1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]
[1, 0, 4, 5, 0, 7, -1, -1, -1, -1, -1]
as your specification ask for.
It basically runs two indexes through the array, the fromix index advances by one no matter what. The toidx index only advances if the value at fromidx is different to the last one transferred. The initial value of the last one transferred is set to something different to the first element, so as to ensure the first element is transferred.
In other words, on each iteration where that condition is true, the value at the from index is copied to the toidx index, the toidx index is incremented, and the last value is updated. If the value at fromidx is the same as the last transferred, the toidx index is not updated.
Then, at the end, all the remaining values are set to -1.
Since your specs call for the rest of the array to be populated with -1, that's what I've done in the above code.
However, your sample result does not contain the negative values so, on the off chance that you need the array truncated rather than filled with -1, you basically replace the while loop at the end with an array truncation, so that its size is now toidx.
In Python, you could do that with something like:
array = array[0:toidx]
There's no need for your inner loop. You just have to keep track of what the last value you visited was, then start skipping until you find a 'new' number. e.g. in pseudo code
previous = null;
newarray = array();
newpos = 0;
for (i = 0; i < oldarray.length; i++) {
if (oldarray[i] == previous) {
continue; // got a duplicate value, so skip it.
} else {
newarray[newpos++] = oldarray[i];
previous = oldarray[i];
}
}
for (i = newpos; i < oldarray.length; i++) {
newarray[i] = -1; // fill in any empty slots
}
Now you're down to O(n).
If you use a LinkedList instead, you could use a ListIterator for the loop, storing the value of the previous value in the list and calling ListIterator.remove if it equals the current value.

Solving Codility Algorithm

I tried the sample demo at Codility website, and posted my solution but I've a simple mistake but couldn't determine it.
The problem is described here (The problem is only described please don't care about the analysis there as that wasn't not my solution)
http://codility.com/cert/view/certHNPV9B-7M4GAQR985B54VYF/details
my solution is here:
public static int min_router_peripherality ( int[] T ) {
// write your code here
int sum=0;
for(int i=0;i<T.length;i++) sum+= T[i];
int min = sum;
int index = 0;
int array [] = new int [T.length];
for(int i=0;i<T.length;i++) {
min = sum -T[i];
array[i] = min;
}
int x = array[0];
for (int i=0; i<array.length;i++)
{
if (array[i]<x)
{
x = array[i];
index = i;
}
}
return index;
}
What I see as mistakes are the following:
for(int i=0;i<T.length;i++)
sum+= T[i];
Here you treat T[i] like some weight. But Node-Ids are no weights. Summing up node ids is useless.
Then: The text says: "if T[P] = Q and P ≠ Q, ...". I don't see anything which takes this into account.
Then: Not understanding the algorithm I tried a simple "line" like this:
int[] T = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9};
The result is 8. But in a line the result should be somewhere in the middle.
Therefore I doubt that the linked page shows the results of the code you have posted.
When looking at the results I would say that your program is correct, but too slow to successfully complete all test cases. So you need to come up with better algorithm.
EDIT: As Ivan Benko Ivan Benko noted, your solution is O(N), so i looked at your code and I came up with a following input:
{ 4, 9, 4, 9, 4, 4, 8, 9, 0, 0 }
Although it is not the example input, it does describe the same network as in the task description. So the output should be same, but your solution gives a different answer.
All I did was look at your code, and the first thing I noticed is that it doesn't look like you need that array array at all, or that third for loop. The second for loop can just keep track of the lowest min value it generates as it goes, along with the index associated with that lowest min value, rather than storing all the values and making a second run like you're doing now.
Edit:
Like everyone else, I assumed that your link was to your own results. I'm not going to post an answer, because I think you're supposed to come up with that yourself. However, it looks to me like you got confused where they said "find the sum of distances to all other nodes", and that might be why you're starting off summing up the entire array. The array they're passing into your function isn't a set of distances by any means. It's a list of existing connections. If the first element (the one at the 0 index) in the array is a 5, then that means Router 0 has a connection to Router 5. So it looks to me like you're approaching it all wrong.
Two adjacent node has a one edge and its weight is 1.

Categories