public static void remove (int[] arr, int toRemove)
"It should remove the value toRemove from the array. The remaining elements should just be shifted toward the beginning of the array. (The array's size will not change). Since the array will now have one fewer element in use, the original last element should just be replaced with 0. If there is more than one occurrence of toRemove in the array, only the FIRST occurrence should be removed. If the array has no elements, it should just have no effect".
So far, I have this:
public static void remove(int[] arr, int toRemove) {
for(int i = 0; i <= arr.length - 1; i++) {
if(arr[i] == toRemove) {
arr[i] = arr[i + 1];
arr[toRemove] = 0;
}
}
}
I have a main method with an array with its contents: [3, 5, 7, 8, 12, 2] and a call saying remove(array, 5). However, my array prints out [3, 7, 7, 8, 12, 0], when it should print out [3, 7, 8, 12, 2, 0].
Can someone let me know what I have wrong and explain it?
Here is an approach, similar to what I described in the comments above.
import java.util.Arrays;
public class main
{
// tip: arguments are passed via the field below this editor
public static void main(String[] args)
{
int[] arr = {3, 5, 7, 8, 5, 12, 2};
remove(arr, 5);
System.out.println(Arrays.toString(arr)); // [3, 7, 8, 5, 12, 2, 0]
}
public static void remove(int[] arr, int toRemove) {
int idx = -1;
// determine first occurrence of toRemove
for(int i = 0; i < arr.length; i++) {
if(arr[i] == toRemove) {
idx = i;
break;
}
}
// if not found, return
if(idx == -1) return;
// shift other elements down
for(int i = idx; i < arr.length-1; i++) {
arr[i] = arr[i+1];
}
// set last element to 0
arr[arr.length-1] = 0;
}
}
You need to have two indexes:
fromIndex is the one that go on the array.
toIndex is the place that the item need to be.
public static void remove(int[] arr, int toRemove) {
int toIndex = 0;
for(int fromIndex = 0; fromIndex < arr.length; fromIndex++) {
//paste number only if its not 'toRemove'
if(arr[fromIndex] != toRemove) {
arr[toIndex] = arr[fromIndex];
toIndex++;
}
}
//Fill the rest with 0
for (; toIndex < arr.length; toIndex++)
arr[toIndex] = 0;
}
this works if there are multiple indexes with the value of toRemove
You should use System.arraycopy. It's fast.
Try this.
public static void remove(int[] arr, int toRemove) {
for(int i = 0, length = arr.length; i < length; i++) {
if(arr[i] == toRemove) {
System.arraycopy(arr, i + 1, arr, i, length - i - 1);
arr[length - 1] = 0;
break;
}
}
}
public static void main(String[] args) throws IOException {
int[] a0 = {0, 1, 2, 3, 4};
remove(a0, 0);
System.out.println(Arrays.toString(a0));
int[] a4 = {0, 1, 2, 3, 4};
remove(a4, 4);
System.out.println(Arrays.toString(a4));
int[] a5 = {0, 1, 2, 3, 4};
remove(a5, 5);
System.out.println(Arrays.toString(a5));
int[] a6 = {0};
remove(a6, 0);
System.out.println(Arrays.toString(a6));
int[] a7 = {};
remove(a7, 0);
System.out.println(Arrays.toString(a7));
}
output:
[1, 2, 3, 4, 0]
[0, 1, 2, 3, 0]
[0, 1, 2, 3, 4]
[0]
[]
Related
I've been going through this MOOC.fi Java course and got to the problem about developing a selection sort algorithm on this page (https://java-programming.mooc.fi/part-7/2-algorithms). I don't have the solutions, so I was wondering if anyone here could help me solve this problem. Basically, I got through all the steps uptil Part 4, but when I tried to make the selection sort method, my method only sorted the numbers correctly until it got to the second to last number, and then it started switching the numbers incorrectly. Can anyone look over my code and tell me where I went wrong?
import java.util.Arrays;
public class MainProgram {
public static void main(String[] args) {
// Testing methods
// Test Part 1
int[] numbers = {6, 5, 8, 7, 11};
System.out.println("Smallest: " + MainProgram.smallest(numbers));
// Testing Part 2
System.out.println("Index of the smallest number: " + MainProgram.indexOfSmallest(numbers));
// Testing Part 3
System.out.println(MainProgram.indexOfSmallestFrom(numbers, 0));
System.out.println(MainProgram.indexOfSmallestFrom(numbers, 1));
System.out.println(MainProgram.indexOfSmallestFrom(numbers, 2));
// Testing Part 4
int[] numbers2 = {3, 2, 5, 4, 8};
System.out.println(Arrays.toString(numbers2));
MainProgram.swap(numbers2, 1, 0);
System.out.println(Arrays.toString(numbers2));
MainProgram.swap(numbers2, 0, 3);
System.out.println(Arrays.toString(numbers2));
// Testing Part 5
int[] numbers3 = {8, 3, 7, 9, 1, 2, 4};
MainProgram.sort(numbers3);
}
// Part 1
public static int smallest(int[] array) {
int smallest = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i] < smallest) {
smallest = array[i];
}
}
return smallest;
}
// Part 2
public static int indexOfSmallest(int[] array){
int smallest = array[0];
int i;
int finalIndex = 0;
for (i = 0; i < array.length; i++) {
if (array[i] < smallest) {
smallest = array[i];
finalIndex = i;
}
}
return finalIndex;
}
// Part 3
public static int indexOfSmallestFrom(int[] table, int startIndex) {
int smallest = table[startIndex];
int i = startIndex;
int finalIndex = 0;
for (i = startIndex; i < table.length; i++) {
if (table[i] < smallest) {
smallest = table[i];
finalIndex = i;
}
}
return finalIndex;
}
// Part 4
public static void swap(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
// Part 5
public static void sort(int[] array) {
int smallestIndex;
for (int i = 0; i < array.length; i++) {
smallestIndex = indexOfSmallestFrom(array, i);
swap(array, smallestIndex, i);
System.out.println(Arrays.toString(array));
}
}
}
Here is the wrong output:
[1, 3, 7, 9, 8, 2, 4]
[1, 2, 7, 9, 8, 3, 4]
[1, 2, 3, 9, 8, 7, 4]
[1, 2, 3, 4, 8, 7, 9]
[1, 2, 3, 4, 7, 8, 9]
[8, 2, 3, 4, 7, 1, 9]
[9, 2, 3, 4, 7, 1, 8]
In the 3 block you set the
finalIndex = 0;
It should be set to the startIndex
I have managed to create both arrays, however I can't figure out how to combine the two arrays. Every tutorial I see merges them as such:
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
// Output: 3, 4, 5, 6, 8, 9
What I need is something that would output: 3, 3, 3, 4, 5, 5, 6, 6, 8, 9
Here is the code I have written so far:
import java.util.Scanner;
public class Merger {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] arr1 = new int[10000];
int[] arr2 = new int[10000];
int[] merged = new int[20000];
int a1 = 0;
int a2 = 0;
int size = -1;
int size2 = -1;
int sizecheck = 0;
int size2check = 0;
System.out
.println("Enter the values for the first array, up to 10,000 values, enter a negative number to quit");
for (int i = 0; i < arr1.length; i++) {
arr1[i] = scan.nextInt();
merged[i] = arr1[i];
if (arr1[i] <= 0) {
break;
}
if (size <= arr1[i]) {
size = arr1[i];
sizecheck++;
}
a1++;
}
System.out
.println("Enter the values for the second array, up to 10,000 values, enter a negative number to quit");
for (int i = 0; i < arr2.length; i++) {
arr2[i] = scan.nextInt();
merged[i + a1] = arr2[i];
if (arr2[i] <= 0) {
break;
}
if (size2 <= arr2[i]) {
size2 = arr2[i];
size2check++;
}
a2++;
}
System.out.println("First Array: ");
for (int i = 0; i < a1; i++) {
System.out.print(" " + arr1[i]);
}
System.out.println("\nSecond Array: ");
for (int i = 0; i < a2; i++) {
System.out.print(" " + arr2[i]);
}
}
}
This prints both arrays out, however does not combine and sort the two.
Here's the code ! There may be a faster/easier way to do it but this one works as long as the 2 arrays are sorted
public static void main(String[] args) {
int[] a1 = {1, 2, 3, 5};
int[] a2 = {1, 3, 4, 4, 4, 5};
int[] a3 = merge(a1, a2);
for (int i : a3) {
System.out.print(i);
}
}
public static int[] merge(int[] a1, int[] a2) {
int[] a3 = new int[a1.length + a2.length];
int indexA1 = 0;
int indexA2 = 0;
for (int i = 0; i < a3.length; i++) {
int n;
if (indexA1 == a1.length && indexA2 < a2.length) {
n = a2[indexA2];
indexA2++;
} else if (indexA1 < a1.length && indexA2 == a2.length) {
n = a1[indexA1];
indexA1++;
} else {
if (a1[indexA1] < a2[indexA2]) {
n = a1[indexA1];
indexA1++;
} else {
n = a2[indexA2];
indexA2++;
}
}
a3[i] = n;
}
return a3;
}
I assume that you are not yet familiar with Streams, but I would like to give you an example of what you can do with them.
Add import
import java.util.stream.IntStream;
Add this at the end of your main method
System.out.println("");
IntStream arr1Stream = IntStream.of(arr1).limit(a1); //creates an InStream with the first a1 values of arr1
IntStream arr2Stream = IntStream.of(arr2).limit(a2);
int[] both = IntStream.concat(arr1Stream, arr2Stream).sorted().toArray(); //combines the two streams, sorts them an converts them to an Array
System.out.println(Arrays.toString(both)); //easy way to print an array
The easiest way is to use a Stream.
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
Stream both arrays.
flatMap them to a single IntStream
sort them
convert to an array
int [] combined = Stream.of(arr1,arr2)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
System.out.println(Arrays.toString(combined));
Prints
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
A non-stream approach can be done as follows:
// increase arr1 to make room for arr2
int oldLen = arr1.length;
arr1 = Arrays.copyOf(arr1, arr1.length+arr2.length);
// copy arr2 starting at 0, to arr1 starting at the old length
// positon of arr1 for a length of arr2
System.arraycopy(arr2, 0, arr1, oldLen, arr2.length);
// sort and print
Arrays.sort(arr1);
System.out.println(Arrays.toString(arr1));
Prints
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
Although your question, as asked, said nothing about merging sorted arrays, here is how you would do it.
The algorithm is simple. Just iterate thru each array and compare current values.
if arr1[i] <= arr2[k], copy arr1[i] to result, advance i by 1
else copy arr2[k] to result, advance k by 1.
in all cases the index to result, r, is advanced by 1
public int[] merge(int[] arr1, int[] arr2) {
// result array
int[] result = new int[arr1.length + arr2.length];
int r = 0;
int k = 0;
int i = 0;
// Iterate thru the arrays, copying the lowest or equal value
// to the target array. This process will cease when one of the arrays
// has been fully processed.
for (; i < arr1.length && k < arr2.length; ) {
for (; k < arr2.length && i < arr1.length;) {
if (arr1[i] <= arr2[k]) {
result[r++] = arr1[i++];
}else {
result[r++] = arr2[k++];
}
}
}
Having reached this far in the algorithm, one of the arrays must have been completely processed. So try and copy both. For the empty array, the while loop basically acts like an if statement.
while (i < arr1.length) {
result[r++] = arr1[i++];
}
while (k < arr2.length) {
result[r++] = arr2[k++];
}
// return the result
return result;
}
public class Merger {
public static void main(String[] args) {
int[] arr1 = { 3, 3, 5, 6, 8, 9 };
int[] arr2 = { 3, 4, 5, 6 };
int[] res = merge(arr1, arr2);
System.out.println(Arrays.toString(res));
}
public static int[] merge(int[] arr1, int[] arr2) {
int[] res = new int[arr1.length + arr2.length];
for (int i = 0, a1 = 0, a2 = 0; i < res.length; i++) {
if (a1 == arr1.length)
res[i] = arr2[a2++];
else if (a2 == arr2.length)
res[i] = arr1[a1++];
else
res[i] = arr1[a1] <= arr2[a2] ? arr1[a1++] : arr2[a2++];
}
return res;
}
}
A simple solution can be written using the classes, Arrays and System.
Steps:
Copy elements of arr1[] into a new array (say, output[]) whose size is the sum of the sizes of the given arrays.
Copy the elements of arr2[], after the element of arr1[], into output[]
Sort output[]
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr1 = { 3, 3, 5, 6, 8, 9 };
int[] arr2 = { 3, 4, 5, 6 };
// Copy elements of arr1[] into a new array whose size is the sum of the sizes
// of the given arrays
int[] output = Arrays.copyOf(arr1, arr1.length + arr2.length);
// Copy the elements of arr2[], after the element of arr1[], into output[]
System.arraycopy(arr2.clone(), 0, output, arr1.length, arr2.length);
// Sort output[]
Arrays.sort(output);
// Display output[]
System.out.println(Arrays.toString(output));
}
}
Output:
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
You can use System.arraycopy method for this purpose:
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
// create a new array of total length
int[] arr3 = new int[arr1.length + arr2.length];
// copy first array to the beginning of the total array
System.arraycopy(arr1, 0, arr3, 0, arr1.length);
// copy second array to the end of the total array
System.arraycopy(arr2, 0, arr3, arr1.length, arr2.length);
// sort the total array
Arrays.sort(arr3);
System.out.println(Arrays.toString(arr3));
// [3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
I have the following code:
public static void nextPermutationArray(int[] v) {
int x = 1;
int y;
Random r = new Random();
while (x < v.length) {
y = x + r.nextInt(v.length - x);
int temp = v[x];
v[x] = v[y];
v[y] = temp;
x++;
}
}
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
}
The program returns me:
0321
0231
0231
0132
My question is: is there any way to edit the method nextPermutationArray to avoid random permutations like 0231. In other words, the method should return 4 unrepeatable elements.
You can store each permutation that has already been returned in a static variable of type int[][]. If you get a result that is already in the array, you can make another permutation. Repeat until you have a new permutation. But be careful, this can make an endless loop if you want to produce more permutations than possible!
This should print out all the permutation without storing them in a HashMap or a List
public static boolean nextPermutationArray(int[] a) {
int i = a.length - 2;
while (i >= 0 && a[i] >= a[i + 1]) {
i--;
}
if (i < 0) {
return false;
}
int j = a.length - 1;
while (a[i] >= a[j]) {
j--;
}
int t = a[i];
a[i] = a[j];
a[j] = t;
Collections.reverse(Arrays.asList(Arrays.copyOfRange(a, i + 1, a.length)));
return true;
}
it will return true until there is a premutation to use it run this code
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
do {
System.out.println(Arrays.toString(a));
} while (nextPermutationArray(a));
}
output is
[0, 1, 2, 3]
[0, 1, 3, 2]
[0, 2, 3, 1]
[0, 3, 2, 1]
[1, 3, 2, 0]
[2, 3, 1, 0]
[3, 2, 1, 0]
I'm trying to write a method that takes a sorted array and an integer, creates a new array that is 1 size larger, and inserts the new integer and keeps it sorted.
I've tried a few different implementations and had them to work - but for this specific one, I can't grasp where it's going wrong.
int[] array1 = new int[]{1, 2, 3, 4, 6, 7, 8};
int[] printArray = insert(array1, 5);
are the arrays, and the method is
public static int[] insert(int[] a, int k) {
int[] s = new int[a.length + 1];
for(int i = 0; i < a.length; i++) {
if(k < s[i]) {
s[i] = k;
for(int j = i + 1; j < s.length; j++) {
s[j] = a[i];
i++;
}
return s;
} else {
s[i] = a[i];
}
}
return s;
}
This method prints out 1, 2, 3, 4, 6, 7, 8, 0, instead of 1, 2, 3, 4, 5, 6, 7, 8.
Change
if(k < s[i]) {
to
if(k < a[i]) {
in line 4.
Actually in the following line you are creating an array with all elements zero:
int[] s = new int[a.length + 1];
s[0] to s[7] will be 0.
Your loop counter i runs from 0 to a.length but the point to note is all the elements of array s will be zero. You are comparing k with s[i] which is zero and for that reason the shifting of arrays never happen (if block never executes).
You need to do two things to fix it.
Initialize element zero of s with the value of a[0].
Compare element with previous element to figure out position to insert.
The final code is:
public static int[] insert(int[] a, int k) {
int[] s = new int[a.length + 1];
s[0] = a[0];
for(int i = 1; i < a.length; i++) {
if(k < s[i-1]) {
s[i] = k;
for(int j = i + 1; j < s.length; j++) {
s[j] = a[i];
i++;
}
return s;
} else {
s[i] = a[i];
}
}
return s;
}
Now you will get:
[1, 2, 3, 4, 6, 5, 7, 8]
I would start by using Arrays.copyOf(int[], int) to create a new array that is one larger than the input. Then iterate that array until I reached the index that the new value belongs at. Then use System.arraycopy(Object,int,Object,int,int) to copy the values into the end of the array. That might look something like
public static int[] insert(int[] a, int k) {
int[] s = Arrays.copyOf(a, a.length + 1);
for (int i = 0; i < s.length; i++) {
if (a[i] < k) {
continue;
}
System.arraycopy(a, i, s, i + 1, s.length - i - 1);
s[i] = k;
break;
}
return s;
}
Which I tested with Arrays.toString(int[]) like
public static void main(String s[]) throws IOException {
int[] array1 = new int[] { 1, 2, 3, 4, 6, 7, 8 };
int[] printArray = insert(array1, 5);
System.out.println(Arrays.toString(printArray));
}
And I get the (expected)
[1, 2, 3, 4, 5, 6, 7, 8]
I have two int[] arrays I and J as follows:
int[] I = { 1, 2, 4, 5, 3 };
int[] J = { 8, 7, 6, 3, 2 };
I want to sort I, and then rearrange J using the same indices so the two arrays stay in registration. The result should be:
I = { 1, 2, 3, 4, 5 };
J = { 8, 7, 2, 6, 3 };
I would start by writing a routine to swap elements in an int[]. Something like,
public 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 you could use it and Arrays.toString(int[]) and something like
public static void main(String[] args) {
int[] I = { 1, 2, 4, 5, 3 };
int[] J = { 8, 7, 6, 3, 2 };
for (int i = 0; i < I.length - 1; i++) {
for (int j = i + 1; j < I.length; j++) {
if (I[i] > I[j]) {
swap(I, i, j);
swap(J, i, j);
}
}
}
System.out.printf("I = %s%n", Arrays.toString(I));
System.out.printf("J = %s%n", Arrays.toString(J));
}
Output is (as requested)
I = [1, 2, 3, 4, 5]
J = [8, 7, 2, 6, 3]
This can also be accomplished with Java 8 IntStream and additional Pair class representing a 2-tuple (I know, it's a bit ugly because we have to copy the values back to the array):
public class Main {
public static void main(String[] args) {
final int[] I = {1, 2, 4, 5, 3};
final int[] J = {8, 7, 6, 3, 2};
List<Pair> pairs = IntStream.range(0, I.length)
.mapToObj(n -> new Pair(I[n], J[n]))
.sorted((p1, p2) -> p1.i - p2.i)
.collect(Collectors.toList());
for (int k=0; k < pairs.size(); k++) {
Pair p = pairs.get(k);
I[k] = p.i;
J[k] = p.j;
}
System.out.println(Arrays.toString(I));
System.out.println(Arrays.toString(J));
}
public static class Pair {
public int i,j;
public Pair(int i, int j) {
this.i = i;
this.j = j;
}
}
}
Output:
[1, 2, 3, 4, 5]
[8, 7, 2, 6, 3]
Keeping the arrays in sync isn't very pretty, I would strongly suggest to model this properly by using an array of tuple objects instead. Then, it's much simpler:
public class Main {
public static void main(String[] args) {
final Pair[] P = {new Pair(1,8), new Pair(2,7), new Pair(4,6),
new Pair(5,3), new Pair(3,2)};
Arrays.sort(P, (p1, p2) -> p1.i - p2.i);
System.out.println(Arrays.toString(P));
}
public static class Pair {
public int i,j;
public Pair(int i, int j) {
this.i = i;
this.j = j;
}
#Override
public String toString() {
return String.format("(%d, %d)", i, j);
}
}
}
Output:
[(1, 8), (2, 7), (3, 2), (4, 6), (5, 3)]
As #ajb has noted in the comments above, the easiest way to implement this is to use a class modelling a tuple.
This has the advantage that you can use the Arrays.sort builtin which saves you from writing your own sorting algorithm. On the other hand, there is the additional overhead of transferring data from the Tuples to the raw arrays.
However, you may find that in your application you are able to directly use the Tuple objects without transferring them back to arrays.
import java.util.*;
class Tuple implements Comparable<Tuple>
{
int x;
int y;
Tuple(int a, int b)
{
x = a;
y = b;
}
public int compareTo(Tuple another)
{
return Integer.compare(x, another.x);
}
}
class Main
{
public static void main(String args[])
{
int a[] = {1, 2, 4, 5, 3};
int b[] = {8, 7, 6, 3, 2};
Tuple arr[] = new Tuple[a.length];
for (int i=0;i<a.length;i++)
arr[i] = new Tuple(a[i], b[i]);
Arrays.sort(arr);
for (int i=0;i<a.length;i++)
{
a[i] = arr[i].x;
b[i] = arr[i].y;
}
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
}
And the output:
[1, 2, 3, 4, 5]
[8, 7, 2, 6, 3]