Moving and merging elements in array? - java

I'm quite new to Java but I've got the basics...
So I have an array of 4 ints which I need to move to the front of the array, or merge them if they are equal so:
{0,1,0,2} turns into {1,2,0,0}
{2,1,0,2} turns into {2,1,2,0}
{1,1,0,0} turns into {2,0,0,0}
{0,2,0,2} turns into {4,0,0,0}
{1,1,3,3} turns into {2,6,0,0}
{2,2,2,2} turns into {4,4,0,0} etc...
Here's what I have so far:
public void combine(int[] row)
{
for (int i = 0; i < row.length-1; i++)
{
if (row[i] == 0 && row[i+1] > 0) //move
{
row[i] = row[i+1];
row[i+1] = 0;
}
if (row [i] == row[i+1] && row[i] > 0) //merge
{
row[i] = 2 * row[i];
row[i+1] = 0;
}
}
System.out.println(row[0]);
System.out.println(row[1]);
System.out.println(row[2]);
System.out.println(row[3]);
}
The problem is:
{0,1,0,2} becomes {1,0,2,0}
{0,2,0,2} becomes {2,0,2,0}
{1,1,3,3} becomes {2,3,3,0}
{2,2,2,2} becomes {4,2,2,0}
It doesn't merge fully, or it only moves and merges once for some reason? I would like to know what I am doing wrong so I can learn, thanks!
Please, could anyone help me with this? I would really appreciate it... Thanks!

It appears that you will need to perform a move to front, then merge your elements and then move to front again. The merge is relatively simple to implement, examine even indexes in the array; if two adjacent elements are equal multiply one by two and set the other to 0. Something like,
private static void merge(int[] arr) {
for (int i = 0; i + 1 < arr.length; i += 2) {
if (arr[i] == arr[i + 1]) {
arr[i] *= 2;
arr[i + 1] = 0;
}
}
}
I would begin with swap, to move elements in the array like
private static void swap(int[] arr, int i, int j) {
if (i == j) {
return;
}
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
Then for move to front, examine each element from the left; when we get a 0 begin looking from the right for a non-zero and then swap
private static void moveToFront(int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
for (int j = arr.length - 1; j > i; j--) {
if (arr[j] != 0) {
swap(arr, i, j);
}
}
}
}
}
Next, combine; move to front, merge and then move to front again
public static void combine(int[] row) {
moveToFront(row);
merge(row);
moveToFront(row);
}
Finally, we can test it like
public static void main(String[] args) {
int[][] arr = { { 0, 1, 0, 2 }, // turns into {1,2,0,0}
{ 2, 1, 0, 2 }, // turns into {2,1,2,0}
{ 1, 1, 0, 0 }, // turns into {2,0,0,0}
{ 0, 2, 0, 2 }, // turns into {4,0,0,0}
{ 1, 1, 3, 3 }, // turns into {2,6,0,0}
{ 2, 2, 2, 2 } };// turns into {4,4,0,0}
for (int[] a : arr) {
combine(a);
System.out.println(Arrays.toString(a));
}
}
And I get (as requested)
[1, 2, 0, 0]
[2, 1, 2, 0]
[2, 0, 0, 0]
[4, 0, 0, 0]
[2, 6, 0, 0]
[4, 4, 0, 0]

The problem is the move and merge in your code is only 1-step moving, while the move and merge could be 2 or more steps moving. This is not a java question but a algorithm one.
This is a two-pointer question by using i and j, i is to record the position you are going to move number in and j is the position you have reached out to the furthest to get number from.

Related

Return a version of the given array where each zero value in the array is replaced by the largest odd value to the right of the zero in the array

If there is no odd value to the right of the zero, leave the zero as a zero.
zeroMax([0, 5, 0, 3]) → [5, 5, 3, 3]
zeroMax([0, 4, 0, 3]) → [3, 4, 3, 3]
This is from CodingBat: https://codingbat.com/prob/p187050
There are certainly better implementations than mine, but it would help me tremendously to see where I went wrong.
It is the findAndReplace method that is not doing its job. I don't see a reason as to why it insists that intarray[0] = 0, and that is where I am stuck. I have implemented the method separately from this class, and it works as expected.
Below is my work:
public class ZeroMax {
public static int[] zeroMax(int[] intarray) {
int max = largestOdd(intarray);
System.out.println("largest odd is " + max);
return findAndReplace1(intarray, 0, max);
}
//method returns the largest odd value or returns zero
public static int largestOdd(int[] arr) {
int maxodd = 0;
int n = arr.length;
int temp = 0;
//this is just a bubble sort
for (int i = 0; i < n; i++) {
for (int j = 1; j < (n - i); j++) {
if (arr[j - 1] > arr[j]) {
//swap elements
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
//this finds the largest number that is an odd
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] % 2 != 0) {
maxodd = arr[i];
break;
} else {
continue;
}
}
return maxodd;
}
//following returns an array where the zeros (int find)
// can be replaced with the largest odd (int replace)
public static int[] findAndReplace1(int[] intarray, int find, int replace) {
for (int i = 0; i < intarray.length; i++) {
//System.out.println(intarray[i]);
if (intarray[i] == find) {
intarray[i] = replace;
}
}
return intarray;
}
}
I believe that the key to your problem is
… to the right of the zero in the array
One given example is zeroMax([0, 5, 0, 3]) → [5, 5, 3, 3]. In your code you are finding the greatest odd value in the entire array. 5 in this case. Then you are replacing every 0 in the array with 5.
Original array: [0, 5, 0, 3]
Expected result: [5, 5, 3, 3]
Your result: [5, 5, 5, 3]
So it seems that you still have a bit of coding to do.
There are certainly better implementations than mine, …
Your implementation, your design and code style, are just fine. Only except for the lamentable fact that it didn’t solve the problem correctly.
An idea how to solve the problem. The following should work in all cases:
Iterate backward from the end array until the first (so the rightmost) odd number.
If there isn’t any odd number in the array, you’re done.
Store the odd number into a variable holding the greatest odd number encountered so far.
Continue iterating backward from the index you came to down to index 0. For each index:
If the number at the index is odd and greater than the hitherto greatest odd number, store the number as the greatest odd number.
If the number is 0, store the greatest odd number until now into the array at this index.
I was reading the question wrong. This is the successful solution that I came up with after more careful reading:
public int[] zeroMax(int[] intarray) {
int maxvalue = 0;
int index = 0;
for (int i = 0; i < intarray.length; i++) {
if (intarray[i] == 0) {
index = i;
//call max value method
maxvalue = maxvalue(intarray, index);
intarray[i] = maxvalue;
}
}
return intarray;
}
public int maxvalue(int[] intarray, int index) {
int maxvalue = 0;
for (int i = index; i < intarray.length; i++) {
if ((intarray[i] % 2 == 1) && (intarray[i] > maxvalue)) {
maxvalue = intarray[i];
}
}
return maxvalue;
}
You can use Arrays.stream(T[],int,int) method to iterate over this array from the current index to the end, then filter odd numbers and get max of them:
public static void main(String[] args) {
int[] arr1 = {0, 5, 0, 3};
int[] arr2 = {0, 4, 0, 3};
int[] arr3 = {0, 3, 0, 4};
replaceZeros(arr1);
replaceZeros(arr2);
replaceZeros(arr3);
System.out.println(Arrays.toString(arr1)); // [5, 5, 3, 3]
System.out.println(Arrays.toString(arr2)); // [3, 4, 3, 3]
System.out.println(Arrays.toString(arr3)); // [3, 3, 0, 4]
}
private static void replaceZeros(int[] arr) {
// iterate over the indices of array
IntStream.range(0, arr.length)
// filter zero elements
.filter(i -> arr[i] == 0)
// for each zero iterate over the elements
// of array from the current index to the end
.forEach(i -> Arrays.stream(arr, i, arr.length)
// filter odd elements
.filter(e -> e % 2 != 0)
// take the max element and
// replace the current one
.max().ifPresent(e -> arr[i] = e));
}

Finding the largest area of equal numbers in matrix java

I have a task.I need to find the biggest area with equal numbers(e.g. neighbours by row or column). The program that i made works fine,but the problem is that if i have the following matrix:
{ 1, 3, 2, 2, 2, 4 }
{ 3, 1, 3, 2, 4, 4 }
{ 4, 3, 1, 2, 3, 3 }
{ 4, 3, 1, 3, 3, 1 }
{ 4, 3, 3, 3, 1, 1 }
The program will print 10.Okay maybe some of you may say that it's because i add 1 to the final result,yeah that's true but if i don't add 1 ,and if the number at position [1][1] was 3 instead of 1 ,i would get 12 witch is wrong,so that`s why i add 1.So my question is do you have any suggestions about optimazing the algorithm..if yes,i would be very thankful to hear them :)..
Here is my code:
protected int counter = 0;
protected int max = 1;
protected enum eState {
Vi,
InPr,
Unvi
};
public void recNodeMatrix(int i, int j, eState st[][],int [][]matr,int n,int k) {
st[i][j] = eState.InPr;
for (int r = 0; r < n; r++) {
for (int c = 0; c < k; c++) {
if ((matr[i][j] == matr[r][c])
&& ((((i+j) - (r + c)) == 1) || (((i+j) - (r + c)) == -1))
&& ((st[r][c] == eState.Unvi))) {
counter++;
recNodeMatrix(r, c, st,matr,n,k);
}
}
}
st[i][j] = eState.Vi;
}
public void Zad17() {
int n=5,k=6;
eState st[][] = new eState[n][k];
int[][] matr = new int[][] {
{ 1, 3, 2, 2, 2, 4 },
{ 3, 1, 3, 2, 4, 4 },
{ 4, 3, 1, 2, 3, 3 },
{ 4, 3, 1, 3, 3, 1 },
{ 4, 3, 3, 3, 1, 1 } };
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
st[i][j] = eState.Unvi;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
if(st[i][j] == eState.Unvi) {
recNodeMatrix(i, j, st,matr,n,k);
if(max<counter)
max=counter;
counter =0;
}
}
}
System.out.print(max+1);
}
Probably the best way to solve this problem is with a union-find data structure: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Initially, each cell is its own set, and then you merge the sets for every pair of adjacent cells that have equal numbers in them.
When you're done, the answer is the size of the biggest set. Since you have to keep track of the set sizes anyway, use union-by-size instead of union-by-rank.
Applying a bit of cleverness, you can implement the union-find with just an array of N*K integers -- one for each cell. Each integer is either the index of the parent set or -size for roots.
This solves the problem in about linear time, and will probably be faster in practice than flood-fill solutions using a similar amount of memory.

Returning the number of unique numbers in a sorted array [duplicate]

This question already has answers here:
How to efficiently remove duplicates from an array without using Set
(48 answers)
Closed 7 years ago.
I was asked to write a method that accepts a sorted array, removes any duplicate elements found in the array and then places a 0 at the end of the array for every duplicate element found.
It is also supposed to return the number of unique elements found in the array.
Here is my method:
public static int removeDups(int[] arr) {
int j = 0;
int i = 1;
int numDups = 0;
while(i < arr.length) {
if (arr[i] == arr[j]) {
i++;
numDups++;
}
else {
arr[++j] = arr[i++];
}
}
for (int k = j+1; k < arr.length; k++) {
arr[k] = 0;
}
return (j);
}
It successfully finds all the duplicate numbers in the array and places the correct number of 0s at the end, but it doesn't always return the correct value for the number of unique elements.
For example, for the array:
{ 6 10 19 21 23 26 27 36 38 45 }
the number of unique elements should be 10, but it returns 9.
What am I doing wrong?
As it can be seen, j is used as the index of the last unique element.
In an array, i'th index is actually the i + 1'th element counted from 1.
So, you have to return j + 1 instead of j from your method.
Here is a solution to your problem. It keeps track of two pointers, one which only advances when a value gets written to the array, and the other which touches every element of the array in sequential order. When one or more duplicates are encountered, the second pointer keeps advancing, while the first pointer stays put, waiting to write a non-duplicate value. Finally, the code iterates over the remainder of the array from the first pointer, writing out zeroes until the end.
public static int removeDups(int[] arr) {
if (arr == null) {
return null;
}
if (arr.length == 0 || arr.length == 1) {
return arr;
}
int prevIndex = 0;
for (int i=1; i < arr.length; ++i) {
if (arr[prevIndex] != arr[i]) {
arr[prevIndex+1] = arr[i];
++prevIndex;
}
}
for (int i=prevIndex+1; i < arr.length; ++i) {
arr[i] = 0;
}
return prevIndex+1;
}
int[] arr = {1, 2, 3, 3, 4, 5, 6, 6, 6, 10};
removeDups(arr);
System.out.println(Arrays.toString(arr));
Output:
[1, 2, 3, 4, 5, 6, 10, 0, 0, 0]
This code has been tested using IntelliJ and it appears to be working.
Try this!
static int getUniqueElements(int [] sortedArr){
int duplicateCount = 0;
int [] tempArr = sortedArr;
int j=0;
boolean isNewValue = true;
for(int i=1;i<tempArr.length;i++){
if(sortedArr[j] != tempArr[i]){
isNewValue = true;
sortedArr[++j] = tempArr[i];
}else{
if(isNewValue){
isNewValue = false;
duplicateCount++;
}
}
}
for(j++;j<sortedArr.length;j++){
sortedArr[j] = 0;
duplicateCount++;
}
return (sortedArr.length-duplicateCount);
}
public static void main(String[] args) {
int[] arr = {1, 3, 3, 3, 3, 6, 6, 7, 8, 8};
System.out.println("Unique Count:"+ getUniqueElements(arr));
System.out.println(Arrays.toString(arr));
}
OutPut:
Unique Count:2
[1, 3, 6, 7, 8, 0, 0, 0, 0, 0]
Since in the given array 1,7 are unique.
Note: tried with your example array {6, 10, 19, 21, 23 ,26 ,27 ,36 ,38, 45 } also
My solution is as(assuming elements can repeat only twice):
public static int removeDups(int[] arr) {
int i = 0;
int numDups = 0;
while (i < arr.length - 1 - numDups) {
if (arr[i] == arr[i + 1]) {
numDups++;
for (int m = i + 1; m < arr.length - numDups; m++) {
arr[m] = arr[m + 1];
}
arr[arr.length - numDups] = 0;
}
i++;
}
return arr.length-numDups;
}

Sum consecutive even numbers and consecutive odd numbers in an array

I have a code that sums the consecutive even numbers and consecutive odd numbers, then adds them to an arraylist. This process should be repeated until there are no more consecutive odd or even numbers in the list. Then returns the size of the arraylist.
I used nested for loops and the problem is the loops check the same index which doesn't make sense.
Here's my code:
public static int SumGroups(int[] arr) {
ArrayList<Integer> arl = new ArrayList<Integer>();
int even = 0, odd = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] % 2 == 0) {
even += arr[i];
if (arr[j] % 2 == 0) {
even += arr[j];
} else {
arl.add(even);
even = 0;
break;
}
} else {
odd += arr[i];
if (arr[j] % 2 != 0) {
odd += arr[j];
} else {
arl.add(odd);
odd = 0;
break;
}
}
}
}
return arl.size();
}
My Question is:
How to prevent loops from checking the same index ?
in other words, how to make my code sums the consecutive even numbers and consecutive odd numbers ?
Input:
int arr[]={2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9};
Output:
6 // [2, 1, 10, 5, 30, 15]
I think the following code should solve the problem, if you do not want to output the size simply return `sums` instead of `sums.size()`
public static int sumGroupsRecursively(int[] arr) {
List<Integer> numbersToSum = IntStream.of(arr).boxed().collect(Collectors.toList());
List<Integer> currentSumList = sumSublist(numbersToSum);
List<Integer> nextSumList = sumSublist(currentSumList);
while (currentSumList.size() != nextSumList.size()) {
currentSumList = nextSumList;
nextSumList = sumSublist(currentSumList);
}
return nextSumList.size();
}
public static List<Integer> sumSublist(List<Integer> list) {
int current = list.get(0);
int currentSum = 0;
List<Integer> sums = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (current % 2 == list.get(i) % 2) {
currentSum += list.get(i);
} else {
sums.add(currentSum);
current = list.get(i);
currentSum = current;
}
}
sums.add(currentSum);
return sums;
}
If you need to do this in one function what I would discourage because it is harder to read you could use code like this.
public static Integer sumSublist(int[] arr) {
List<Integer> sums = new ArrayList<>();
sums.add(0);
int i = 0;
while (i < arr.length - 1) {
int current = arr[i];
int currentSum = 0;
while (current % 2 == arr[i] % 2) {
currentSum += arr[i];
if (i >= arr.length - 1) {
break;
}
i++;
}
if (currentSum % 2 == sums.get(sums.size()-1) % 2) {
sums.set(sums.size() - 1, sums.get(sums.size()-1) + currentSum);
} else {
sums.add(currentSum);
}
}
return sums.size();
}
You are entering your first for loop passing in arr. Inside the first for loop you enter a second for loop passing in arr a second time. This means that you enter the second for loop as many times as there are elements in arr and transverse arr in the second for loop every single time.
for example, if arr.length() was 2 you would transverse arr 3 times. Once in your outer for loop and twice (once for each element in arr) in your inner loop.
Second, by adding both the odd and even numbers to your arraylist, you are doing nothing but reconstructing arr but in an arraylist rather than array. Therefor, returning arl.size() is the exact same as returning arr.length() which is already known and much easier to do.
Despite that, here is how I would calculate the sum of the odd and evens. I add both to different arraylists. You'll need to figure out exactly what you need to return though because your description is off.
public void test(){
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
int testOfEven = 6;
int testOfOdd = 9;
int sumOfEven = 0;
int sumOfOdd = 0;
ArrayList evens = new ArrayList<Integer>();
ArrayList odds = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if ((arr[i]%2) == 0)
{
evens.add(arr[i]);
sumOfEven += arr[i];
}
else
{
odds.add(arr[i]);
sumOfOdd += arr[i];
}
}
assertEquals(testOfEven, sumOfEven);
assertEquals(testOfOdd, sumOfOdd);
}
after playing some time, here is my version:
public static int SumGroups(final int[] arr) {
if (arr.length > 0) {
int n, sum, psum;
psum = sum = n = arr[0] & 1; // parity of first number in sequence
int s = 1; // at least one element in array
int f = 0; // discard first parity change
for (int i = 1; i < arr.length; i++) {
if (n == (arr[i] & 1)) {
sum = (sum + n) & 1; // both even or odd, just increase sum
} else {
s += (psum ^ sum) & f; // compare sums parity
psum = sum; // store current sum's parity
sum = n = arr[i] & 1; // new first number in sequence
f = 1; // do not discard sums parity next time
}
}
s += (psum ^ sum) & f; // array ended, check parity of last sum
return s;
}
return 0;
}
I've put comments, but still some additional notes:
basic idea is the same as #PKuhn, just checked for some edge cases (empty array, integer overflow)
we don't need to have array of sums, we need just previous sum and check parity of it with newly calculated one
sum = (sum + n) & 1 - we don't need to calculate whole sum, we need just parity of the sum
s += (psum ^ sum) & f - we need to increase swap counter only if parity changed, xor helps us to get 1 if changed and 0 if not
Here is the list of tests which I've used:
Assert.assertEquals(6, SumGroups(new int[] { 2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9 }));
Assert.assertEquals(6, SumGroups(new int[] { 0, 0, 0, 0, 2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 3, 3 }));
Assert.assertEquals(1, SumGroups(new int[] { 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 3, 3, 3, 3, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 3, 2, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 1, 3, 3, 2, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 1, 2, 3, 3, 2, 3, 3, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 3, 3, 2, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE, 3 }));
public void findEvenOdd(int a[]){
Boolean flip = false;
int sum = 0, i, m = 0;
for (i = 0; i < a.length; i++) {
if (flip) {
System.out.print(sum + "\t");
sum = a[i];
flip = !flip;
if (i + 1 < a.length && (a[i] % 2 != a[i + 1] % 2))
flip = !flip;
m++;
} else {
sum += a[i];
if (i + 1 < a.length && (a[i] % 2 != a[i + 1] % 2))
flip = !flip;
m++;
}
}
if(m!=a.length-1)
System.out.print(a[a.length-1] + "\t");
}

Move 0's to end of array

I need to move all 0's in an array to the end of the array.
Example: [1, 10, 0, 5, 7] should result in [1, 10, 5, 7, 0].
I am open to doing a reverse loop or a regular loop.
I cannot create a new array.
Here is what I have so far:
for (int i = arr.length; i <= 0; --i) {
if (arr[i] != 0) {
arr[i] = arr.length - 1;
}
}
Thanks!
SIZE(n) where n = arr.size, retain ordering:
Create an array that is the same size as the initial array you need to remove 0s from. Iterate over the original array and add each element to the new array provided it is not 0. When you encounter a 0, count it. Now, when you've reached the end of the first array, simply add the counted number of 0s to the end of the array. And, even simpler, since Java initializes arrays to 0, you can forget about adding the zeroes at the end.
Edit
Since you have added the additional constraint of not being able to create a new array, we need to take a slightly different approach than the one I've suggested above.
SIZE(1)
I assume the array needs to remain in the same order as it was before the 0s were moved to the end. If this is not the case there is another trivial solution as detailed in Brads answer: initialize a "last zero" index to the last element of the array and then iterate backwards swapping any zeros with the index of the last zero which is decremented each time you perform a swap or see a zero.
SIZE(1), retain ordering:
To move the 0s to the end without duplicating the array and keeping the elements in the proper order, you can do exactly as I've suggested without duplicating the array but keeping two indices over the same array.
Start with two indices over the array. Instead of copying the element to the new array if it is not zero, leave it where it is and increment both indices. When you reach a zero, increment only one index. Now, if the two indices are not the same, and you are not looking at a 0, swap current element the location of the index that has fallen behind (due to encountered 0s). In both cases, increment the other index provided the current element is not 0.
It will look something like this:
int max = arr.length;
for (int i = 0, int j = 0; j < max; j++) {
if (arr[j] != 0) {
if (i < j) {
swap(arr, i, j);
}
i++
}
}
Running this on:
{ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 }
yeilds:
{ 1, 2, 3, 4, 5, 0, 0, 0, 0, 0 }
I made a fully working version for anyone who's curious.
Two choices come to mind
Create a new array of the same size, then Iterate over your current array and only populate the new array with values. Then fill the remaining entries in the new array with "zeros"
Without creating a new array you can iterate over your current array backwards and when you encounter a "zero" swap it with the last element of your array. You'll need to keep a count of the number of "zero" elements swapped so that when you swap for a second time, you swap with the last-1 element, and so forth.
[Edit] 7 years after originally posting to address the "ordering" issue and "last element is zero" issues left in the comments
public class MyClass {
public static void main(String[] args) {
int[] elements = new int[] {1,0,2,0,3,0};
int lastIndex = elements.length-1;
// loop backwards looking for zeroes
for(int i = lastIndex; i >=0; i--) {
if(elements[i] == 0) {
// found a zero, so loop forwards from here
for(int j = i; j < lastIndex; j++) {
if(elements[j+1] == 0 || j == lastIndex) {
// either at the end of the array, or we've run into another zero near the end
break;
}
else {
// bubble up the zero we found one element at a time to push it to the end
int temp = elements[j+1];
elements[j+1] = elements[j];
elements[j] = temp;
}
}
}
}
System.out.println(Arrays.toString(elements));
}
}
Gives you...
[1, 2, 3, 0, 0, 0]
Basic solution is to establish an inductive hypothesis that the subarray can be kept solved. Then extend the subarray by one element and maintain the hypothesis. In that case there are two branches - if next element is zero, do nothing. If next element is non-zero, swap it with the first zero in the row.
Anyway, the solution (in C# though) after this idea is optimized looks like this:
void MoveZeros(int[] a)
{
int i = 0;
for (int j = 0; j < a.Length; j++)
if (a[j] != 0)
a[i++] = a[j];
while (i < a.Length)
a[i++] = 0;
}
There is a bit of thinking that leads to this solution, starting from the inductive solution which can be formally proven correct. If you're interested, the whole analysis is here: Moving Zero Values to the End of the Array
var size = 10;
var elemnts = [0, 0, 1, 4, 5, 0,-1];
var pos = 0;
for (var i = 0; i < elemnts.length; i++) {
if (elemnts[i] != 0) {
elemnts[pos] = elemnts[i];
pos++;
console.log(elemnts[i]);
}
}
for (var i = pos; i < elemnts.length; i++) {
elemnts[pos++] = 0;
console.log(elemnts[pos]);
}
int arrNew[] = new int[arr.length];
int index = 0;
for(int i=0;i<arr.length;i++){
if(arr[i]!=0){
arrNew[index]=arr[i];
index++;
}
}
Since the array of int's is initialized to zero(according to the language spec). this will have the effect you want, and will move everything else up sequentially.
Edit: Based on your edit that you cannot use a new array this answer doesnt cover your requirements. You would instead need to check for a zero(starting at the end of the array and working to the start) and swap with the last element of the array and then decrease the index of your last-nonzero element that you would then swap with next. Ex:
int lastZero = arr.length - 1;
if(arr[i] == 0){
//perform swap and decrement lastZero by 1 I will leave this part up to you
}
/// <summary>
/// From a given array send al zeros to the end (C# solution)
/// </summary>
/// <param name="numbersArray">The array of numbers</param>
/// <returns>Array with zeros at the end</returns>
public static int[] SendZerosToEnd(int[] numbersArray)
{
// Edge case if the array is null or is not long enough then we do
// something in this case we return the same array with no changes
// You can always decide to return an exception as well
if (numbersArray == null ||
numbersArray.Length < 2)
{
return numbersArray;
}
// We keep track of our second pointer and the last element index
int secondIndex = numbersArray.Length - 2,
lastIndex = secondIndex;
for (int i = secondIndex; i >= 0; i--)
{
secondIndex = i;
if (numbersArray[i] == 0)
{
// While our pointer reaches the end or the next element
// is a zero we swap elements
while (secondIndex != lastIndex ||
numbersArray[secondIndex + 1] != 0)
{
numbersArray[secondIndex] = numbersArray[secondIndex + 1];
numbersArray[secondIndex + 1] = 0;
++secondIndex;
}
// This solution is like having two pointers
// Also if we look at the solution you do not pass more than
// 2 times actual array will be resume as O(N) complexity
}
}
// We return the same array with no new one created
return numbersArray;
}
In case if question adds following condition.
Time complexity must be O(n) - You can iterate only once.
Extra
space complexity must be O(1) - You cannot create extra array.
Then following implementation will work fine.
Steps to be followed :
Iterate through array & maintain a count of non-zero elements.
Whenever we encounter a non-zero element put at count location in array & also increase the count.
Once array is iterated completely put the zeros at end of array till the count reach to original length of array.
public static void main(String args[]) {
int[] array = { 1, 0, 3, 0, 0, 4, 0, 6, 0, 9 };
// Maintaining count of non zero elements
int count = -1;
// Iterating through array and copying non zero elements in front of array.
for (int i = 0; i < array.length; i++) {
if (array[i] != 0)
array[++count] = array[i];
}
// Replacing end elements with zero
while (count < array.length - 1)
array[++count] = 0;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
Time complexity = O(n), Space Complexity = O(1)
import java.util.Scanner;
public class ShiftZeroesToBack {
int[] array;
void shiftZeroes(int[] array) {
int previousK = 0;
int firstTime = 0;
for(int k = 0; k < array.length - 1; k++) {
if(array[k] == 0 && array[k + 1] != 0 && firstTime != 0) {
int temp = array[previousK];
array[previousK] = array[k + 1];
array[k + 1] = temp;
previousK = previousK + 1;
continue;
}
if(array[k] == 0 && array[k + 1] != 0) {
int temp = array[k];
array[k] = array[k + 1];
array[k + 1] = temp;
continue;
}
if(array[k] == 0 && array[k + 1] == 0) {
if(firstTime == 0) {
previousK = k;
firstTime = 1;
}
}
}
}
int[] input(Scanner scanner, int size) {
array = new int[size];
for(int i = 0; i < size; i++) {
array[i] = scanner.nextInt();
}
return array;
}
void print() {
System.out.println();
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ShiftZeroesToBack sztb = new ShiftZeroesToBack();
System.out.print("Enter Size of Array\t");
int size = scanner.nextInt();
int[] input = sztb.input(scanner, size);
sztb.shiftZeroes(input);
sztb.print();
}
}
let's say we have an array
[5,4,0,0,6,7,0,8,9]
Let's assume we have array elements between 0-100, now our goal is to move all 0's at the end of the array.
now hold 0 from the array and check it with non zero element if any non zero element found swap with that element and so on, at the end of the loop we will find the solution.
here is the code
for (int i = 0; i < outputArr.length; i++)
{
for (int j = i+1; j < outputArr.length; j++)
{
if(outputArr[i]==0 && outputArr[j]!=0){
int temp = outputArr[i];
outputArr[i] = outputArr[j];
outputArr[j] = temp;
}
}
print outputArr[i]....
}
output:
[5,4,6,7,8,9,0,0,0]
Here is how i have implemented this.
Time complexity: O(n) and Space Complexity: O(1)
Below is the code snippet:
int arr[] = {0, 1, 0, 0, 2, 3, 0, 4, 0};
int i=0, k = 0;
int n = sizeof(arr)/sizeof(arr[0]);
for(i = 0; i<n; i++)
{
if(arr[i]==0)
continue;
arr[k++]=arr[i];
}
for(i=k;i<n;i++)
{
arr[i]=0;
}
output: {1, 2, 3, 4, 0, 0, 0, 0, 0}
Explanation: using another variable k to hold index location, non-zero elements are shifted to the front while maintaining the order. After traversing the array, non-zero elements are shifted to the front of array and another loop starting from k is used to override the remaining positions with zeros.
This is my code with 2 for loops:
int [] arr = {0, 4, 2, 0, 0, 1, 0, 1, 5, 0, 9,};
int temp;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
{
for (int j = i + 1; j < arr.length; j++)
{
if (arr[j] != 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
break;
}
}
}
}
System.out.println(Arrays.toString(arr));
output: [4, 2, 1, 1, 5, 9, 0, 0, 0, 0, 0]
public static void main(String[] args) {
Integer a[] = {10,0,0,0,6,0,0,0,70,6,7,8,0,4,0};
int flag = 0;int count =0;
for(int i=0;i<a.length;i++) {
if(a[i]==0 ) {
flag=1;
count++;
}else if(a[i]!=0) {
flag=0;
}
if(flag==0 && count>0 && a[i]!=0) {
a[i-count] = a[i];
a[i]=0;
}
}
}
This is One method of Moving the zeroes to the end of the array.
public class SeparateZeroes1 {
public static void main(String[] args) {
int[] a = {0,1,0,3,0,0,345,12,0,13};
movezeroes(a);
}
static void movezeroes(int[] a) {
int lastNonZeroIndex = 0;
// If the current element is not 0, then we need to
// append it just in front of last non 0 element we found.
for (int i = 0; i < a.length; i++) {
if (a[i] != 0 ) {
a[lastNonZeroIndex++] = a[i];
}
}//for
// We just need to fill remaining array with 0's.
for (int i = lastNonZeroIndex; i < a.length; i++) {
a[i] = 0;
}
System.out.println( lastNonZeroIndex );
System.out.println(Arrays.toString(a));
}
}
This is very simple in Python. We will do it with list comprehension
a =[0,1,0,3,0,0,345,12,0,13]
def fix(a):
return ([x for x in a if x != 0] + [x for x in a if x ==0])
print(fix(a))
int[] nums = { 3, 1, 2, 5, 4, 6, 3, 2, 1, 6, 7, 9, 3, 8, 0, 4, 2, 4, 6, 4 };
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
list1.add(nums[i]);
} else if (nums[i] != 3) {
list2.add(nums[i]);
}
}
List<Integer> finalList = new ArrayList<>(list2);
finalList.addAll(list1);
}
}
int[] nums = {3,1,2,5,4,6,3,2,1,6,7,9,3,8,0,4,2,4,6,4};
int i = 0;
for(int j = 0, s = nums.length; j < s;) {
if(nums[j] == 3)
j++;
else {
int temp = nums[i];
nums[i] = nums[j];``
nums[j] = temp;
i ++;
j ++;
}
}
For Integer array it can be as simple as
Integer[] numbers = { 1, 10, 0, 5, 7 };
Arrays.sort(numbers, Comparator.comparing(n -> n == 0));
For int array :
int[] numbers = { 1, 10, 0, 5, 7 };
numbers = IntStream.of(numbers).boxed()
.sorted(Comparator.comparing(n -> n == 0))
.mapToInt(i->i).toArray();
Output of both:
[1, 10, 5, 7, 0]
Lets say, you have an array like
int a[] = {0,3,0,4,5,6,0};
Then you can sort it like,
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]==0 && a[j]!=0){
a[i]==a[j];
a[j]=0;
}
}
}
public void test1(){
int [] arr = {0,1,0,4,0,3,2};
System.out.println("Lenght of array is " + arr.length);
for(int i=0; i < arr.length; i++){
for(int j=0; j < arr.length - i - 1; j++){
if(arr[j] == 0){
int temp = arr[j];
arr[j] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
}
}
for(int x = 0; x < arr.length; x++){
System.out.println(arr[x]);
}
}
Have a look at this function code:
vector<int> Solution::solve(vector<int> &arr) {
int count = 0;
for (int i = 0; i < arr.size(); i++)
if (arr[i] != 0)
arr[count++] = arr[i];
while (count < arr.size())
arr[count++] = 0;
return arr;
}
import java.io.*;
import java.util.*;
class Solution {
public static int[] moveZerosToEnd(int[] arr) {
int j = 0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] != 0) {
swap(arr, i, j);
j++;
}
}
return arr;
}
private static void swap(int arr[], int i, int j){
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
public static void main(String[] args) {
int arr[] =new int[] {1, 10, 0, 2, 8, 3, 0, 0, 6, 4, 0, 5, 7, 0 };
System.out.println(Arrays.toString(moveZerosToEnd(arr)));
}
}
Reimplemented this in Python:
Pythonic way:
lst = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
for i, val in enumerate(lst):
if lst[i] == 0:
lst.pop(i)
lst.append(0)
print("{}".format(lst))
#dcow's implementation in python:
lst = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
i = 0 # init the index value
for j in range(len(lst)): # using the length of list as the range
if lst[j] != 0:
if i < j:
lst[i], lst[j] = lst[j], lst[i] # swap the 2 elems.
i += 1
print("{}".format(lst))
a = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
count = 0
for i in range(len(a)):
if a[i] != 0:
a[count], a[i] = a[i], a[count]
count += 1
print(a)
#op [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]

Categories

Resources