Swapping two elements in an array - java

I'm doing mooc.fi, my code works but it won't submit.
errors I'm getting
the method swap does not work correctly with parameter 4, 7, 8, 6 index1=0 index2=3
the result was 4, 7, 8, 6 but it should have been 6, 7, 8, 4
and
the method sort does not work correctly with parameter 10, 20, 6, -1, 13, 11
the result was 10, 20, 6, -1, 13, 11 but it should have been -1, 6, 10, 11, 13, 20
I know the errors are connected but I'm not too sure what to do to fix this, any help is appreciated! thank you!
My Code:
import java.util.Arrays;
public class Main {
public static int smallest(int[] array) {
int start = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i] < start) {
start = array[i];
}
}
return start;
}
public static int indexOfTheSmallest(int[] array) {
for (int i = 0; i < array.length; i++) {
if (array[i] == smallest(array)) {
return i;
}
}
return 0;
}
public static int indexOfTheSmallestStartingFrom(int[] array, int index) {
int minIndex = index;
for (int i = index; i < array.length; i++) {
if (array[i] < array[minIndex]) {
minIndex = i;
}
}
return minIndex;
}
public static void swap(int[] array, int index1, int index2) {
int hold = 0;
for (int i = 0; i < array.length; i++) {
hold = array[index1];
array[index1] = array[index2];
array[index2] = hold;
}
}
public static void sort(int[] array) {
System.out.println(Arrays.toString(array));
for (int i = 0; i < array.length; i++) {
swap(array, i, indexOfTheSmallestStartingFrom(array, i));
System.out.println(Arrays.toString(array));
}
}
public static void main(String[] args) {
int[] values = {8, 5, 3, 7, 9, 6, 1, 2, 4};
sort(values);
}
}

This algorithm is designed very badly. both smallest and indexOfSmallest use a loop, this will degrade geometrically.
The swap should not be scanning the entire array as you only want to swap two elements, not all of them!
You're effectively doing a whack version of a bubble-sort, but in a really convoluted way with too many loops. This will start to perform horribly with any decent sized list.
A much simpler version can be found here

You do not need a loop for the swap method. As you only want to change the two element once and not n-times (which results in not swapping them at all if n is an even number).

public int[] swapArrayElement(int arr[], int a, int b) {
int index1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == a || arr[i] == b) {
index1 = i;
if (arr[i] == a) {
for (int k = index1; k < arr.length; k++) {
if (arr[k] == b) {
arr[k] = arr[index1];
arr[index1] = b;
}
}
return arr;
} else if (arr[i] == b) {
{
for (int k = index1; k < arr.length; k++) {
if (arr[k] == a) {
arr[k] = arr[index1];
arr[index1] = a;
}
}
}
return arr;
}
}
}
return arr;
}

Related

Need help to understand an implementation of the Counting Sort sort algorithm

This code is about algorithms and datastructures. This code runs perfectly and i just have some questions on it because it seems like i don't understand two points. So my questions for that is:
which informations are in the countingArray?
how often is the while loop executed?
public class CountingSort {
public static void main(String[] args) {
int[] m1 = { 1, 17, 3, 1, 4, 9, 4, 4 };
System.out.println("unsorted:");
output(m1);
int min1 = rangeMin(m1);
int max1 = rangeMax(m1);
countingSort(m1, min1, max1);
System.out.println("sorted:");
output(m1);
int[] m2 = { -1, 13, 3, -1, -4, 9, -4, 4 };
System.out.println("unsorted:");
output(m2);
int min2 = rangeMin(m2);
int max2 = rangeMax(m2);
countingSort(m2, min2, max2);
System.out.println("sorted:");
output(m2);
}
public static void output(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + ", ");
}
System.out.println();
}
public static int rangeMin(int[] a) {
int minimum = a[0];
for (int i = 1; i < a.length; i++) {
if (a[i] < minimum)
minimum = a[i];
}
return minimum;
}
public static int rangeMax(int[] array) {
int maximum = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > maximum)
maximum = array[i];
}
return maximum;
}
public static void countingSort(int[] array, int rangeMin, int rangeMax) {
int[] countingArray = new int[rangeMax - rangeMin + 1];
for (int i : array) {
countingArray[i - rangeMin]++;
}
int c = 0;
for (int i = rangeMin; i <= rangeMax; i++) {
while (countingArray[i - rangeMin] > 0) {
array[c] = i;
c++;
countingArray[i - rangeMin]--;
}
}
}
}
CountingSort has O(n) time and space complexity. You iterate (i.e. use for loop) twice.
public class CountingSort {
public static void main(String... args) {
proceed(1, 17, 3, 1, 4, 9, 4, 4);
System.out.println("---");
proceed(-1, 13, 3, -1, -4, 9, -4, 4);
}
public static void proceed(int... arr) {
System.out.print("unsorted: ");
print(arr);
countingSort(arr);
System.out.print("sorted: ");
print(arr);
}
public static void print(int... arr) {
System.out.println(Arrays.stream(arr)
.mapToObj(i -> String.format("%2d", i))
.collect(Collectors.joining(",")));
}
public static void countingSort(int... arr) {
int min = Arrays.stream(arr).min().orElse(0);
int max = Arrays.stream(arr).max().orElse(0);
// contains amount of number in the unsorted array
// count[0] - amount of min numbers
// count[count.length - 1] - amount of max numbers
int[] count = new int[max - min + 1];
for (int i : arr)
count[i - min]++;
// fill source array with amount of numbers
for (int i = 0, j = 0; i < count.length; i++)
for (int k = 0; k < count[i]; k++, j++)
arr[j] = min + i;
}
}

Selection Sort does not return a sorted array

I am trying to write a selection sort where I find the maximum in the (sub)array bounded by the int upper, and swap the current value with the max.
I have written three separate methods—I have a method for finding the index of the maximum value in the array, a method for swapping two values, and a sort method for actual sorting. I've tried debugging but am not very good at it...
public static void sort(Comparable[] array)
{
int maxindex = 0;
for(int k=0; k<array.length; k++)
{
maxindex = findMax(array, array.length-k);
if(maxindex < k)
swap(array, k, maxindex);
}
}
public static int findMax(Comparable[] array, int upper)
{ //"upper" controls where the inner loop of the selection sort ends
Comparable max = array[0];
int maxindex = 0;
for(int i = 1; i<upper; i++)
{
if(max.compareTo(array[i])<0)
{
max = array[i];
maxindex = i;
}
}
return maxindex;
}
public static void swap(Object[] array, int a, int b)
{
Object save = array[b];
array[b] = array[a];
array[a] = save;
}
I generate a random array and call the sort and print out the "sorted" array, except that the printed array is not sorted at all...
I took your code and made some modifications in sort as well as findMax function. Now, we are getting correct output.
sort function: I'm not sure why you have condition before the swap, it will prevent some of the findMax from swapping. Also, my guess is you are doing array.length - k because you might want to keep the maximum in the last index and loop through to find next maximum and so on. To do that your logic seems to be wrong.
findMax function: Index should start at 0 and go till upper.
See the below code for details:
public static void sort(int[] array) {
int maxindex = 0;
for(int k=array.length - 1; k >= 0; k--) {
maxindex = findMax(array, k);
swap(array, k, maxindex);
}
}
public static int findMax(int[] array, int upper) {
//"upper" controls where the inner loop of the selection sort ends
int max = array[0];
int maxindex = 0;
for(int i = 0; i <= upper; i++) {
if(max < array[i]) {
max = array[i];
maxindex = i;
}
}
return maxindex;
}
Input: [4, 2, 3, 8, 7, 1, 9, 10, 15, 12, 11, 13]
Output: [1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 15]
Since comparable is a raw type. References to generic type Comparable should be parameterised. Not recommended to use raw datatype, unless it is necessary.
The below program has few modifications done from your code. You can compare and it runs on O(n^2) complexity.
The main issue in your code is in findMax() function, the function is made static by hardcoding the value.
import java.util.Arrays;
public class XYZ {
public static void main(String args[]) {
sort(new Integer[] { 1, 5, 2, 11, 4 });
}
public static void sort(Comparable[] array) {
int maxindex = 0;
for (int k = 0; k < array.length; k++) {
maxindex = findMax(array, k);
if (maxindex > k)
swap(array, k, maxindex);
// System.out.println(Arrays.toString(array));
}
}
public static int findMax(Comparable[] array, int startIndex) {
Comparable max = array[startIndex];
int maxindex = 0;
for (int i = startIndex; i < array.length; i++) {
if (max.compareTo(array[i]) < 0) {
max = array[i];
maxindex = i;
}
}
return maxindex;
}
public static void swap(Object[] array, int a, int b) {
Object save = array[b];
array[b] = array[a];
array[a] = save;
}
}

Getting the Elements that has duplicates in an int array Java

This post - "Java + Count duplicates from int array without using any Collection or another intermediate Array", was also a sample exercise in my book at school, but what I want to do is get the elements that has duplicates without sorting it.
What I did is I removed the duplicates of arrays first, to get only the unique elements and then I compare it to the original array and count how many times the element has been found. But the problem is it doesn't print the correct elements which has duplicates.
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
the correct output should be: 7, 1, 4
but instead it outputs: 7, 6, 1
This is my codes:
//method for removing duplicates
public static int[] removeDuplicates(int[] n) {
int limit = n.length;
for(int i = 0; i < limit; i++) {
for(int j = i + 1; j < limit; j++) {
if(n[i] == n[j]) {
for(int k = j; k < limit - 1; k++) {
n[k] = n[k + 1];
}
limit--;
j--;
}
}
}
int[] uniqueValues = new int[limit];
for(int i = 0; i < uniqueValues.length; i++) {
uniqueValues[i] = n[i];
}
return uniqueValues;
}
//method for getting elements that has duplicates
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
int count = 0;
int limit = u.length;
for(int i = 0; i < u.length; i++) {
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
//main
public static void main(String[] args) {
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
//printing original values
System.out.print(Arrays.toString(num));
System.out.println();
int[] a = getDuplicatedElements(num);
System.out.print("Elements with Duplicates: " + Arrays.toString(a));
}
What's the error in my codes here? Please help thanks...
You have two issues:
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
System.out.println ("unique " + Arrays.toString (u));
int count = 0;
int limit = u.length;
for(int i = 0; i < limit; i++) { // you must use limit instead of u.length
// in order for the loop to terminate
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
i--; // you must decrement i after you find a unique element in u
// otherwise you'll be skipping elements in the u array
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
With those fixes, you'll get the expected output:
Elements with Duplicates: [7, 1, 4]
It's fairly simple when using a stream
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
List<Integer> list = Arrays.stream(num).boxed().collect(Collectors.toList());
list.stream().filter(i -> Collections.frequency(list, i) > 1)
.collect(Collectors.toSet()).forEach(System.out::println);

Merge K sorted arrays of size n using merge algorithm from mergeSort

Problem: Given K sorted arrays of size N each, merge them and print the sorted output.
Sample Input-1:
K = 3, N = 4
arr[][] = { {1, 3, 5, 7},
{2, 4, 6, 8},
{0, 9, 10, 11}} ;
Sample Output-1:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
I know there is a way to do this problem using a priority queue/min heap, but I want to do it using the merge procedure from mergeSort. The idea seems straightforward enough...at each iteration, merge the remaining arrays in groups of two, such that the number of arrays gets halved at each iteration.
However, whenever halving leads to an odd number, this becomes problematic.
My idea is that whenever halving leads to an odd number, we take care of the extra array by merging it with the array formed from the last merge.
The code I have so far is below. This only works on one out of 30 test cases, however:
static int[] mergeArrays(int[][] arr) {
int k = arr.length;
int n = arr[0].length;
if(k < 2){
return arr[0];
}
boolean odd_k;
if(k%2){
odd_k = false;
}
else{
odd_k = true;
}
while(k > 1){
int o;
if(odd_k){
o = (k/2) + 1;
}
else{
o = k/2;
}
int[][] out = new int[o][];
for(int i=0; i < k; i = i + 2){
int[] a;
int[] b;
if(odd_k && i == (k-1)){
b = arr[i];
b = out[i-1];
}
else{
a = arr[i];
b = arr[i+1];
}
out[i] = mergeTwo(a, b);
}
k = k/2;
if(k % 2 == 0){
odd_k = false;
}
else{
odd_k = true;
}
arr = out;
}
return arr[0];
}
static int[] mergeTwo(int[] a, int[] b){
int[] c = new int[a.length + b.length];
int i, j, k;
i = j = k = 0;
while(i < a.length && j < b.length){
if(a[i] < b[j]){
c[k] = a[i];
i++;
k++;
}
else{
c[k] = b[j];
j++; k++;
}
}
if(i < a.length){
while(i < a.length){
c[k] = a[i];
i++; k++;
}
}
if(j < b.length){
while(j < b.length){
c[k] = b[j];
j++; k++;
}
}
return c;
}
We can shorten your mergeTwo implementation,
static int[] mergeTwo(int[] a, int[] b) {
int[] c = new int[a.length + b.length];
int i = 0, j = 0, k = 0; // declare and initialize on one line
while (i < a.length && j < b.length) {
if (a[i] <= b[j]) {
c[k++] = a[i++]; // increment and assign
} else {
c[k++] = b[j++]; // increment and assign
}
}
// No need for extra if(s)
while (i < a.length) {
c[k++] = a[i++];
}
while (j < b.length) {
c[k++] = b[j++];
}
return c;
}
And we can then fix your mergeArrays and shorten it by starting with the first row from the int[][] and then using mergeTwo to concatenate the arrays iteratively. Like,
static int[] mergeArrays(int[][] arr) {
int[] t = arr[0];
for (int i = 1; i < arr.length; i++) {
t = mergeTwo(t, arr[i]);
}
return t;
}
I then tested it with
public static void main(String[] args) {
int arr[][] = { { 1, 3, 5, 7 }, { 2, 4, 6, 8 }, { 0, 9, 10, 11 } };
System.out.println(Arrays.toString(mergeArrays(arr)));
}
And I get (as expected)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
As you say you have merged two arrays at a time. As it is inefficient you can merge all subarrays same time. What you have to do is to find the minimum from every subarray and remember the position of that element.
To do that we can use another array (say curPos) to remember the current position
private int[] merge(int[][] arr)
{
int K = arr.length;
int N = arr[0].length;
/** array to keep track of non considered positions in subarrays **/
int[] curPos = new int[K];
/** final merged array **/
int[] mergedArray = new int[K * N];
int p = 0;
while (p < K * N)
{
int min = Integer.MAX_VALUE;
int minPos = -1;
/** search for least element **/
for (int i = 0; i < K; i++)
{
if (curPos[i] < N)
{
if (arr[i][curPos[i]] < min)
{
min = arr[i][curPos[i]];
minPos = i;
}
}
}
curPos[minPos]++;
mergedArray[p++] = min;
}
return mergedArray;
Probably the easiest way to handle this is to use a queue of arrays. Initially, add all the arrays to the queue. Then, remove the first two arrays from the queue, merge them, and add the resulting array to the queue. Continue doing that until there is only one array in the queue. Something like:
for each array in list of arrays
queue.push(array)
while queue.length > 1
a1 = queue.pop()
a2 = queue.pop()
a3 = merge(a1, a2)
queue.push(a3)
result = queue.pop()
That simplifies things quite a bit, and the problem of "halving" goes away.

How to find every occurrence of a target value in array and return a new array containing the indexes for these values? Java

I am working on a problem and am having a hard time getting it to output the right information.
What I am trying to do is find every occurrence of a target value and put it into a new array and output the indexes of the target values. If no target value is found it returns an empty array. outputs {}
Right now I am getting an error.
findAll():
[I#349b688e
[I#46ed5d9d
java.lang.ArrayIndexOutOfBoundsException
The outputs should be:
outputs {0, 5}
outputs {}
public class FindIndex(){
public FindIndex() {
int a[] = {7, 8, 9, 9, 8, 7};
System.out.println("findAll(): ");
System.out.println(findAll(a, 7));
System.out.print(findAll(a, 2));
}
public int[] findAll(int a[], int num) {
int indexNum = 0;
int arrSize = 0;
// find all occurrence of the target number
for(int i = 0; i < a.length; i++) {
if(a[i] == num) {
arrSize++;
}
}
// create new array
int newArray[] = new int[arrSize];
for(int i = 0; i < a.length; i++) {
if(a[i] == num) {
newArray[indexNum] = i;
}
}
return newArray;
}
public void print(int a[]) {
System.out.print("{");
int i;
for(i = 0; i < a.length - 1; i++) {
System.out.print(a[i] + ", ");
}
if(a.length > 0) {
System.out.print(a[i]);
}
System.out.print("}\n");
}
}
You are never incrementing indexNum, it always remains at 0 and the array keeps on writing the values at this same index.
I think you should have this expression there:
newArray[indexNum++] = i;
For your printing problem, what you're actually printing out ther are the addresses of the arrays returned, not the contents.
What you can do is the following:
System.out.println(Arrays.toString(findAll(a, 7)));
System.out.print(Arrays.toString(findAll(a, 2)));
This will give you the following output:
[5, 0]
[]
Calling findAll(a, 2) gets zero size newArray that's why you get ArrayIndexOutOfBoundsException.
You should check if (arrSize > 0) before doing array with indexes and access it.
I was working with the code and got it to work but it is giving me added zeros in the new array. The output of the top sould be 0, 5 How do I get ride of these added zeros?
int a[] = {7, 8, 9, 9, 8, 7};
int array2[];
// print the occurrence of a target index value
System.out.println("findAll(): ");
array2 = copy(findAll(a, 7));
array2 = copy(findAll(a, 2));
public int[] findAll(int a[], int target) {
int index;
int found = 0;
// find all occurrence of the target number
for(int i = 0; i < a.length; i++) {
if(a[i] == target) {
found = target;
i++;
}
}
// create new array
int newArray[] = new int[found];
for(int i = 0; i < newArray.length; i++) {
if(a[i] == target) {
newArray[i] = i;
i++;
}
}
return newArray;
}
public int[] copy(int newArray[]) {
System.out.print("{");
int i;
for(i = 0; i < newArray.length - 1; i++) {
if (newArray.length == 0) {
System.out.print( " " );
} else {
System.out.print(newArray[i] + ", ");
}
}
System.out.print("}\n");
return newArray;
}
output:
findAll():
{0, 0, 0, 0, 0, 5, }
{}

Categories

Resources