Java array order - java

I have the following array:
int [] mi_array= {9,4,0,0,4,0,3,0,1,8,0};
I want to order the numbers other than 0 on the left, and the 0s on the right, but I find that the function steps on one of the numbers.
The output must be
{9,4,4,3,1,8,0,0,0,0,0}
public class Array {
public static void main(String[] args) {
int [] mi_array= {9,4,4,3,1,8,0,0,0,0,0};
int x=0;
int y=mi_array.length-1;
for (int i=0;i<mi_array.length;i++)
if(mi_array[i]!=0) {
mi_array[x]=mi_array[i];
x++;
}
else {
mi_array[y]=mi_array[i];
y--;
}
for (int i=0;i<mi_array.length;i++)
System.out.println(mi_array[i]);
System.out.println(x);
}
}

Try this.
int[] mi_array = {9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0};
for (int i = 0, j = i + 1, s = mi_array.length; j < s;)
if (mi_array[i] == 0) {
mi_array[i] = mi_array[j];
mi_array[j] = 0;
++j;
} else if (++i >= j)
j = i + 1;
System.out.println(Arrays.toString(mi_array));
// -> [9, 4, 4, 3, 1, 8, 0, 0, 0, 0, 0]

You can use filter and IntStream.concat to merge the parts of the array that are not 0 with the parts that are.
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = IntStream.concat(Arrays.stream(mi_array).filter(i -> i != 0),
Arrays.stream(mi_array).filter(i -> i == 0)).toArray();
System.out.println(Arrays.toString(result));
Demo!
You can also do this:
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = new int[mi_array.length];
final AtomicInteger idx = new AtomicInteger();
Arrays.stream(mi_array).filter(i -> i != 0).forEach(val -> result[idx.getAndIncrement()] = val);
System.out.println(Arrays.toString(result));

Your primary problem here is that you overwrite numbers you haven't already covered.
if (mi_array[i] != 0) {
mi_array[x] = mi_array[i];
x++;
}
x can never exceed i in this code; it starts at 0 just like i does, and increments at most by 1 every loop (and i increments by 1 every loop). So, no problem here; at 'worst' this is mi_array[i] = mi_array[i]; which does nothing.
however...
} else {
mi_array[y]=mi_array[i];
y--;
}
This is much more problematic. Given inputs {9,4,0,0,4,0,3,0,1,8,0};, when i is 2, then mi_array[i] is 0, thus this code runs. y is still 10, so this will end up running: mi_array[10] = 0;. The second 0 occurs when i is 3, and ends up running: mi_array[9] = 0;. And at that point, the 8 at index 9? You deleted it. It cannot be recovered.
The solution
The dumb solution is to make a copy of the array; edit the copy, refer to the original (which you won't change at all). You don't actually end up needing a copy; this code will write every number back, so just make a new array of the same size and write in that.
A slightly more elegant solution will not write 0s at all. Instead, it just writes the non-zeroes (as that code cannot overwrite anything, as shown before), and then at the end, overwrite the rest with zeroes. Now you don't need a copy.

O(n), two-pointer approach:
public static void shiftZeroesRight(int[] array) {
int notZeroPos;
for (int i = 0; i < array.length; i++) {
if (array[i] != 0)
continue;
notZeroPos = i + 1;
while (notZeroPos < array.length && array[notZeroPos] == 0)
++notZeroPos;
if (notZeroPos >= array.length)
break;
array[i] = array[notZeroPos];
array[notZeroPos] = 0;
}
}

Related

How to merge two elements in an array together?

For example you have the 2d array Board as shown below:
{0, 2, 4, 2}
{0, 0, 2, 2}
{2, 2, 0, 0}
{0, 5, 0, 2}
You want it to become:
{0, 2, 4, 2}
{0, 0, 4, 0}
{4, 0, 0, 0}
{0, 5, 0, 2}
When there are 2 elements next to each other you need to merge them to make 4 into the left-most place out of those two elements and then make the 2nd element to be 0.
You want to do this with java.
forgot to show my existing loop, this is it below:
for (int row = 0; row < Board.length; row++){
for (int col = 0; col <= Board.length; col++){
if ((Board[row][col] == Board[row][col +1])){
Board[row][col] = 2 * Board[row][col];
Board[row][col + 1] = 0;
}
}
}
Well, I guess that should work. In the loop, you must be careful not to refer to the wrong ( or non-existing) array element.
public static void main(String[] args) {
int[][] arr = new int[][]{{0, 2, 4, 2}, {0, 0, 2, 2}, {2, 2, 0, 0}, {0, 5, 0, 2}, {2, 2, 2, 2}, {2, 2, 2, 0}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length - 1; j++) {
if (arr[i][j] == arr[i][j + 1]) {
arr[i][j] = arr[i][j] + arr[i][j + 1];
arr[i][j + 1] = 0;
}
}
}
System.out.println(Arrays.deepToString(arr));
}
Here is one way, focusing only array values that equal 2.
iterate the 2D array.
then iterate over each linear array, checking adjacent values and making the changes.
for(int[] arr : v) {
for(int i = 0; i < arr.length-1; i++) {
if (arr[i] == 2 && arr[i+1] == 2) {
arr[i]+= arr[i+1];
arr[i+1] = 0;
}
}
}
for(int arr[]: v) {
System.out.println(Arrays.toString(arr));
}
prints
[0, 2, 4, 2]
[0, 0, 4, 0]
[4, 0, 0, 0]
[0, 5, 0, 2]
Well I assume that Board variable holds array (quick tip, common convention is to name variable in camelCase (first letter lowercase, then each letter of next work upper, if that variable is constant, then convention is SNAKE_UPPER_CASE)
Your first for is pretty okay, the second one too but it assumes that matrix will be always NxN and will fail if thats not the case or it will not work properly (depending if amount of cols is lower or greater than length of array)
Inside it you dont want to check if the values are equal, you want to check if these values are both equal to 2. And you should check if thats not processing of last column of the row, in that case youll get IndexOutOfBoundException because you want to get value of matrix that is not present.
So with small changes, you will achieve what you want. This code will hopefuly shows my thoughts better
public class MergingTwos {
public static void main(String args[]) {
// Init a matrix
int[][] array = new int[][] { { 0, 2, 4, 2 }, { 0, 0, 2, 2 }, { 2, 2, 0, 0 }, { 2, 2, 0, 0 }, { 0, 5, 0, 2 }};
// Iterating over each row of matrix, in veriable i, the current X index is stored
for(int i = 0; i < array.length; i++) {
// Iterating over each column of row, in variable n, the current Y index is stored
for(int n = 0; n < array[i].length; n++) {
// To prevent index out of bound exception, last element of row wont be processed so as we dont want to proceed if given and next value on row are not 2
if(n == array[i].length -1 || array[i][n] != 2 || array[i][n+1] != 2) {
continue;
}
// To value at given coordinates [i,n] you add values of value on coordinates [i, n+1]
array[i][n] = array[i][n] + array[i][n+1];
// And setting next element to 0
array[i][n+1] = 0;
}
}
// Printing the result
for (int[] x : array) {
for (int y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}

Best performance to search a number in a column of a 2d array without cloning the array

I am trying to search for a number in a particular column of a two dimensional array. I tried a few different approach and would like to use stream in Java 8. However, it doesn't seem to be the best performance. Wonder if someone can help?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.map(i -> board[i][col])
.filter(num -> num == number )
.findFirst()
.isPresent();
}
trying to search in a block as well. Any hints?
public boolean isInBlock(int row, int col, int number) {
int r = row - row % 3;
int c = col - col % 3;
for (int i = r; i < r + 3; i++) {
for (int j = c; j < c + 3; j++) {
if (board[i][j] == number)
return true;
}
}
return false;
}
the input data is the following array.
public static int[][] PUZZLE = {
{9,0,0,1,0,0,0,0,5},
{0,0,5,0,9,0,2,0,1},
{8,0,0,0,4,0,0,0,0},
{0,0,0,0,8,0,0,0,0},
{0,0,0,7,0,0,0,0,0},
{0,0,0,0,2,6,0,0,9},
{2,0,0,3,0,0,0,0,6},
{0,0,0,2,0,0,9,0,0},
{0,0,1,9,0,4,5,7,0},
};
This 'stream'-version seems a little bit optimzed, but I think searching for a hit in an array will always be faster the old fashioned way, see Java performance tutorial – How fast are the Java 8 streams?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.anyMatch(i -> (board[i][col] == number) );
}
I made a short attempt with a parallel stream, but the overhead made it far worse.
I think it would be different if the action wasn't a simple compare...
If it's only about speed for a Sudoku-solver/generator maybe you shouldn't loop at all but write the 9 conditions in one return statement
return board[0,col] == number || board[1,col] == number ...
Since this seems to be Sudoku what you could do is store the data redundantly. Don't only store the numbers in "normally" in a two dimensional array, but also have two-dimensional boolean arrays, where you store whether the row/column/block contains the number.
class Sudoku {
private final int[][] puzzle = new int[9][9];
private final boolean[][] rows = new boolean[9][9];
private final boolean[][] columns = new boolean[9][9];
private final boolean[][] blocks = new boolean[9][9];
public void setCell(int row, in column, int number) {
puzzle[row][column] = number;
rows[row][number - 1] = true;
columns[column][number - 1] = true;
blocks[calcBlockId(row, column)][number - 1] = true;
}
// returns a number (0 - 8) identifying a block
// 0 - 2 is first line, 3 - 5 second line, etc.
private int calcBlockId(int row, int column) {
// Left as an exercise to the reader
}
public boolean isInColumn(int col, int number) {
return columns[col][number - 1];
}
public boolean isInBlock(int row, int column, int number) {
return blocks[calcBlockId(row, column)][number - 1];
}
}
This code searches for an element in a 2d array and returns the coordinates of the first match, if such an element is present, or null otherwise:
public static int[] findElement(int[][] arr, int element) {
return IntStream
// iterate through the indexes
// of the rows of the array
.range(0, arr.length)
// for each row
.mapToObj(i -> {
// look for the element in this row
int j = IntStream
// iterate through the indexes
// of the elements of the row
.range(0, arr[i].length)
// filter a matching element
.filter(el -> arr[i][el] == element)
// take first match
.findFirst().orElse(-1);
// if element is present
if (j >= 0)
// return its coordinates
return new int[]{i, j};
else
// or null otherwise
return null;
})
// take first non-null coordinates, if they are present
.filter(Objects::nonNull).findFirst()
// or null otherwise
.orElse(null);
}
// test
public static void main(String[] args) {
int[][] puzzle = {
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0}};
int[] coordinates = findElement(puzzle, 7);
System.out.println(Arrays.toString(coordinates)); // [4, 3]
}
See also:
• Difference between anyMatch and findAny in java 8
• First unique character in a string using LinkedHashMap

How do I correct this For Each loop in java (incorrect output on final test)?

I'm struggling to run this java correctly with a for each loop. It is fine for every test but the last. Could anyone kindly assist in letting me know where I'm going wrong? I feel confident I could do it with a for loop but would like to do it with a for each loop (if suitable).
Drill Question:
Given an array of ints, return true if the sequence of numbers 1, 2, 3 appears in the array somewhere.
arrayOneTwoThree([1, 1, 2, 3, 1]) -> true.
arrayOneTwoThree([1, 1, 2, 4, 1]) -> false.
arrayOneTwoThree([1, 1, 2, 1, 2, 3]) -> true.
For example:
int[] array = {2, 1, 2, 3, 2, 3, 2, 4, 1};
System.out.println(arrayOneTwoThree(array));
Result: true
public static void main(String[] args) {
//int[] array = {2, 1, 2, 3, 2, 3, 2, 4, 1};
//int[] array = {1, 1, 2, 3, 1};
//int[] array = {1, 1, 2, 4, 1};
int[] array = {1, 1, 2, 1, 2, 3};
System.out.println(arrayOneTwoThree(array));
}
public static boolean arrayOneTwoThree(int[] nums) {
for (int num : nums) {
//System.out.print(num);
if (nums[num] == 3 && nums[num-1] == 2 && nums[num-2] == 1)
return true;
}
return false;
}
In the loop, num is NOT the index within the array, it is the value.
I think you are expecting num to be the index, which would be the case if you did a for loop of the form for (int num =0; num < nums.length; num++)
If you want to compare n adiacent elements of array you have to use a loop ending to length - n - 1 : in your case n = 3 so your method can be written like below:
private static boolean arrayOneTwoThree(int[] array) {
final int n = array.length;
if (n < 3) { return false; } //<-- for arrays with less than 3 elements
for (int i = 0; i < n - 2; ++i) {
if (array[i] == 1 && array[i + 1] == 2 && array[i + 2] == 3) {
return true;
}
}
return false;
}
First tree test cases accidentally shoved correct result!
Your code works ONLY for cases, when index of 1 is 1, index of 2 is 2, and index of 3 is 3:
[*, 1, 2, 3, ......... ]
You are probably confused with another programming language. (Maybe for in construction of JavaScript?).
In Java for each over array (or anything else) iterates over values and never over indexes. (As was already specified)
I can see commented out System.out.print(num); why you've ignored it prints values not indexes?
Another issue is ignoring array bounds... Try to examine your code with next array:
int[] array = {2, 3, 2, 1, 2, 3};
It'll end up with ArrayIndexOutOfBoundsException
And answer for your question, how to solve with for each.
Yes, you can introduce external counter, but what would be the sense then?
public static boolean arrayOneTwoThree(int[] nums) {
int i = 0;
for (int num : nums) {
//System.out.print(num);
if (i < 2) continue; // we do not want ArrayIndexOutOfBoundsException happened, right?
if (nums[i] == 3 && nums[num-1] == 2 && nums[num-2] == 1)
return true;
}
return false;
}
If you wish to use for each you should avoid of using indexes to be consistent.
There could be tons of different solutions. You can use some flags or save previous and beforePrevious:
public static boolean arrayOneTwoThree(int[] nums) {
int beforePrevious;
int previous = 0;
int current = 0;
for (int num : nums) {
//System.out.print(num);
beforePrevious = previous;
previous = current;
current = num;
if (current == 3 && previous == 2 && beforePrevious == 1)
return true;
}
return false;
}
Beware: It's just first thought, so this solution may be not optimal and far from perfect, probably you can do better.

Rewrite a Java array based on the values of another array

I've been working in a little Java project but I can't figure out how to overwrite the elements of an array based on the values on another array.
Basically I have two arrays: repeated[] = {1,4,0,0,0,3,0,0} and hand[] = {1,2,2,2,2,6,6,6} and I use repeated[] to count the amount of times a number appears on hand[], and if it is between 3 and 7 it should overwrite the corresponding element in hand[] with a zero but I keep getting this output {1,0,0,2,2,6,0,6} when it should give me {1,0,0,0,0,0,0,0}. What am I doing wrong?
public static void main(String[] args) {
int repeated[] = {1,4,0,0,0,3,0,0};
int hand[] = {1,2,2,2,2,6,6,6};
for(int z=0;z<repeated.length;z++){
if(repeated[z]>=3 && repeated[z]<8){
for(int f:hand){
if(hand[f]==(z+1)){
hand[f]=0;
} } } }
for(int e:hand){
System.out.print(e+",");
}
}
First, the value in repeated is offset by one (because Java arrays start at index zero). Next, you need to test if the value is >= 3 (because 6 only appears 3 times). And, you could use Arrays.toString(int[]) to print your array. Something like,
public static void main(String[] args) {
int repeated[] = { 1, 4, 0, 0, 0, 3, 0, 0 };
int hand[] = { 1, 2, 2, 2, 2, 6, 6, 6 };
for (int z = 0; z < repeated.length; z++) {
if (repeated[hand[z] - 1] >= 3) {
hand[z] = 0;
}
}
System.out.println(Arrays.toString(hand));
}
Output is
[1, 0, 0, 0, 0, 0, 0, 0]

How to implement deleteValues (int values) method for a custom ArrayList?

I am implementing my custom ArrayList class for integers with the help of an array, and I would like to be able to delete a certain value from my array. My problem is when there are many same delete-able value next to each other, I am getting two 0s next to each other which leads to a bug. i tried to solve it for a couple of hours without luck. Here is my code:
int max=10;
public int[] a = new int[max];
#Override
public void deleteValues(int value) {
int tempIndex=0;
for (int i = 0; i <50 ; i++) {
if (a[tempIndex] == value) {
a[tempIndex] = a[tempIndex + 1];
a[tempIndex + 1] = 0;
} else if (a[tempIndex] == 0) {
a[tempIndex] = a[tempIndex + 1];
a[tempIndex + 1] = 0;
} else {
tempIndex++;
}
}
}
My array looks like that before deleting the value (4):
[4, 2, 3, 4, 4, 4, 4, 1, 2, 3]
This is the wrong result after running the code:
[2, 3, 0, 0, 4, 4, 4, 1, 2, 3]
What I would like to achieve:[2, 3, 1, 2, 3, 0, 0, 0, 0, 0]
My question is: What would be the best approach to make the code work, using as few loop as possible?
One of the problems in your code is that you're always copying the element at index tempIndex+1 into tempIndex: it's always the next element.
In fact, after deleting let's say 5 elements from the array, you'll have to copy tempIndex+5 into tempIndex.
I think this is a good way of doing it:
public void deleteValues(int[] a, int value) {
int j=0;
for(int i=0; i<a.length; i++) {
if(a[i]!=value) {
a[j] = a[i];
j++;
}
}
// fill the rest of the array with zeros
while(j<a.length) {
a[j] = 0;
j++;
}
}
Basically, you keep two indices: i and j.
The index i follows the "original" array, while index j follows the "new" array (after deletion).
Index i loops over all the elements: if a[i] is not equal to value, copy it into its new position j and increment both j and i. If a[i] is equal to value, skip it and increment i without incrementing j.
After all the elements have been copied or skipped, fill the end of the array with zeros.
Sample input:
a = {4, 2, 3, 4, 4, 4, 4, 1, 2, 3}
value = 4
Output:
a = {2, 3, 1, 2, 3, 0, 0, 0, 0, 0}
public static void deleteValues(int[] a, int value) {
int newSize = a.length;
int current = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != value) {
if (i != current) {
a[current] = a[i];
newSize--;
}
current++;
}
}
//use first newSize values, for example you can copy to new array
System.out.println("New size = " + newSize);
}
you can use iterator:
List<Integer> numbers = ....
Iterator<Integer> i = numbers.iterator();
while (i.hasNext()) {
Integer num = i.next();
// add here your custom code
i.remove();
}
int tempIndex,index;
for (index = 0, tempIndex = 0; index < valuesArray.length; index++) {
if (valuesArray[index] != valToDelete) {
valuesArray[tempIndex++]=valuesArray[index];
}
}
while(tempIndex<valuesArray.length){
valuesArray[tempIndex++]=0;
}

Categories