Merge Sort Algorithm Code - java

This is code for Merge Sort using the Java programming language.
Where there is an error, it does not give me the correct output.
Is it possible to help me to resolve? Thank you.
I want to work with arrays of type integer.
import java.util.Arrays;
public class Excersize5 {
public void MergeSort(int[] Arr) {
int N = Arr.length;
if (N > 1) {
int Middle = (N) / 2;
int[] A1 = LeftElement(Arr);
int[] A2 = RightElement(Arr);
MergeSort(A1);
MergeSort(A2);
Merge(Arr, A1, A2);
}
}
public void Merge(int[] Result, int[] A1, int[] A2) {
int i = 0;
int j = 0;
for (int k = 0; k < Result.length; k++) {
if (A1[i] >= A2[j] || (i < A1.length &&
A1[i] <= A2[j])) {
Result[k] = A1[i];
i++;
} else {
Result[k] = A2[j];
j++;
}
}
}
public int[] LeftElement(int[] Total) {
int NL = Total.length / 2;
int[] L = new int[NL];
for (int p = 0; p < NL; p++) {
L[p] = Total[p];
}
return L;
}
public int[] RightElement(int[] Total) {
int NL = Total.length / 2;
int NR = Total.length - NL;
int[] R = new int[NR];
for (int q = 0; q < NR; q++) {
R[q] = Total[q];
}
return R;
}
public static void main(String[] args) {
Excersize5 e5 = new Excersize5();
int[] r = {5, 6, 7, 8, 1, 7};
e5.MergeSort(r);
System.out.print(r);
}
}
Output
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at practical4.Excersize5.Merge(Excersize5.java:22) at
practical4.Excersize5.MergeSort(Excersize5.java:14) at
practical4.Excersize5.MergeSort(Excersize5.java:13) at
practical4.Excersize5.MergeSort(Excersize5.java:12) at
practical4.Excersize5.main(Excersize5.java:55) Java Result: 1 BUILD
SUCCESSFUL (total time: 1 second)

You could just use a Vector instead will make it much easier to do. It's because your calling things outside your array length, all of them, and you never return the array result which you should do in some method

Related

MergeSort Algorithm from largest to smallest in java

So I want to use the mergesort algorithm to sort an array filled with numbers from largest to smallest. I have working code for this but I can't seem to make it sort from largest to smallest. I tried playing around with the for loop that has all of those if statements in there but I just couldn't figure it out. Could someone please help.
public class MergeSorter
{
public void merge(int[] a, int l, int h) {
if (h <= l) return;
int result = (l + h) / 2;
merge(a, l, result);
merge(a, result + 1, h);
sort_descend(a, l, result, h);
}
public void sort_descend(int[] a, int l, int result, int h) {
int first_replace[] = new int[result - l + 1];
int second_replace[] = new int[h - result];
for (int i = 0; i < first_replace.length; i++)
first_replace[i] = a[l + i];
for (int i = 0; i < second_replace.length; i++)
second_replace[i] = a[result+ i + 1];
int first_i = 0;
int second_i = 0;
for (int i = l; i < h + 1; i++) {
if (first_i < first_replace.length && second_i < second_replace.length) {
if (first_replace[first_i] < second_replace[second_i]) {
a[i] = first_replace[first_i];
first_i++;
} else {
a[i] = second_replace[second_i];
second_i++;
}
} else if (first_i < first_replace.length) {
a[i] = first_replace[first_i];
first_i++;
} else if (second_i < second_replace.length) {
a[i] = second_replace[second_i];
second_i++;
}
}
}
}
import java.util.Arrays;
public class MergeSortTest
{
public static void main(String args[]) {
int[] array = new int[]{ 6, 1, 3, 8, 3, 9, 2 };
MergeSorter ms = new MergeSorter();
ms.merge(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
}
Your entire logic is correct except one thing. In the sort_descend function, after you copy the array a into first_replace and second_replace, you start comparing the elements using the if condition if (first_replace[first_i] < second_replace[second_i]).
Here, you essentially assign the smaller of the two elements into your array a and this the step which determines whether your array will be sorted in ascending order or descending order.
To sort in descending order, you need to just reverse this sign and you will get the desired output i.e. change the if condition to if (first_replace[first_i] > second_replace[second_i]).
Please refer to the below code to sort an array of integers in descending order.
It is similar to your solution but only one change of the comparator operator on line number 38.
import java.util.Arrays;
public class C
{
public static void main(String args[]) {
int[] array = new int[]{ 6, 1, 3, 8, 3, 9, 2 };
MergeSorter ms = new MergeSorter();
ms.merge(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
}
class MergeSorter {
public void merge(int[] a, int l, int h) {
if (h <= l) return;
int result = (l + h) / 2;
merge(a, l, result);
merge(a, result + 1, h);
sort_descend(a, l, result, h);
}
public void sort_descend(int[] a, int l, int result, int h) {
int first_replace[] = new int[result - l + 1];
int second_replace[] = new int[h - result];
for (int i = 0; i < first_replace.length; i++)
first_replace[i] = a[l + i];
for (int i = 0; i < second_replace.length; i++)
second_replace[i] = a[result + i + 1];
int first_i = 0;
int second_i = 0;
for (int i = l; i < h + 1; i++) {
if (first_i < first_replace.length && second_i < second_replace.length) {
if (first_replace[first_i] >= second_replace[second_i]) {
a[i] = first_replace[first_i];
first_i++;
} else {
a[i] = second_replace[second_i];
second_i++;
}
} else if (first_i < first_replace.length) {
a[i] = first_replace[first_i];
first_i++;
} else if (second_i < second_replace.length) {
a[i] = second_replace[second_i];
second_i++;
}
}
}
}

Is there a test case scenario in which my program will fail?

Problem : You have L, a list containing some digits (0 to 9). Write a function solution(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3. If it is not possible to make such a number, return 0 as the solution. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
Test Cases :
Input:
Solution.solution({3, 1, 4, 1})
Output: 4311
Input:
Solution.solution({3, 1, 4, 1, 5, 9})
Output: 94311
My Program :
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.IntStream;
public class Solution {
static ArrayList<Integer> al = new ArrayList<Integer>();
static ArrayList<Integer> largest = new ArrayList<Integer>();
static int o = 1;
static int po = 0;
static void combinations(String[] digits, String[] data, int start, int end, int index, int r)
{
if (index == r)
{
String temp = "0";
for (int j = 0; j < r; j++)
{
temp = temp + data[j];
// System.out.print(data[j]);
}
Integer d = Integer.parseInt(temp);
al.add(d);
// System.out.println(al);
}
for (int i = start; i <= end && ((end - i + 1) >= (r - index)); i++)
{
data[index] = digits[i];
combinations(digits, data, i + 1, end, index + 1, r);
}
}
static void printCombinations(String[] sequence, int N)
{
String[] data = new String[N];
for (int r = 0; r < sequence.length; r++)
combinations(sequence, data, 0, N - 1, 0, r);
}
static String[] convert(int[] x)
{
String c[] = new String[x.length];
for(int i=0; i < x.length; i++)
{
Integer k = x[i];
if(k==0)
{
o = o * 10;
continue;
}
c[i] = k.toString();
}
// System.out.println(o);
c = Arrays.stream(c).filter(s -> (s != null && s.length() > 0)).toArray(String[]::new);
po = c.length;
// System.out.println("Come"+ Arrays.asList(c));
return c;
}
public static int solution(int[] l) {
if(l.length==0)
return 0;
if(IntStream.of(l).sum()%3==0)
{
String x = "";
Arrays.sort(l);
for (int i = l.length - 1; i >= 0; i--) {
x = x + l[i];
}
return Integer.parseInt(x);
}
printCombinations(convert(l),po);
al.sort(Comparator.reverseOrder());
al.remove(al.size()-1);
al.removeIf( num -> num%3!=0);
if(al.isEmpty())
return 0;
for(int i=0; i< al.size(); i++)
{
Integer n = al.get(i);
printMaxNum(n);
}
// System.out.println(al);
// System.out.println(largest);
return largest.get(0)*o;
}
static void printMaxNum(int num)
{
// hashed array to store count of digits
int count[] = new int[10];
// Converting given number to string
String str = Integer.toString(num);
// Updating the count array
for(int i=0; i < str.length(); i++)
count[str.charAt(i)-'0']++;
// result is to store the final number
int result = 0, multiplier = 1;
// Traversing the count array
// to calculate the maximum number
for (int i = 0; i <= 9; i++)
{
while (count[i] > 0)
{
result = result + (i * multiplier);
count[i]--;
multiplier = multiplier * 10;
}
}
// return the result
largest.add(result);
}
public static void main(String[] args) {
System.out.println(solution(new int[]{9,8,2,3}));
}
}
My Code passes both given test cases and 3 other hidden test cases except one. I tried all possible input combinations but couldn't get to the exact failure. The return type by default is given as int and therefore they would not pass values which give output that does not fit in int. Any other scenario where my code fails?

In my Java merge sort fucntion, even when the condition is false, it is entering the loop. Why?

In my "merge" function, in the while loop, the given condition is a!=null && b!=null, but when b is null, it still enters the while loop and then later gives an error.
int[] merge(int[]a, int[]b)
{
int length = a.length+b.length;
int[]c = new int[length];
while (a!=null && b!=null)
{
if (a[0]<b[0])
{
c[length-1]=a[0];
a = tail(a);
}
else
{
c[length-1]=b[0];
b = tail(b);
}
}
return c;
}
int[] mergeSort(int[]a)
{
if (a.length==1)
return a;
int[] q = new int[a.length];
int[] l = new int[a.length/2];
int [] r = new int[a.length-l.length];
for (int i=0; i<l.length; i++)
{
l[i] = a[i];
}
for (int i=l.length; i<r.length; i++)
{
r[i-l.length] = a[i];
}
q = merge(mergeSort(l), mergeSort(r));
return q;
}
I think, you're facing situation when one of array (either a or b) is already empty, and the other one - still has elements. So, in the merge function you should take this into account.
This is full implementation of your mergeSort:
public class Answer {
public static void main(String[] args) {
int[] unsorted = new int[]{4,3,4,2,1,1,3,3,3,3,3,5,6,6,9,9,10,7,7,8};
System.out.println(Arrays.toString(mergeSort(unsorted)));
}
public static int[] mergeSort(int[]a) {
if (a.length == 1) return a;
int[] q = new int[a.length];
int[] l = new int[a.length / 2];
int [] r = new int[a.length - l.length];
for (int i = 0; i < l.length; i++) {
l[i] = a[i];
}
for (int i = 0; i < r.length; i++) {
r[i] = a[l.length + i];
}
q = merge(mergeSort(l), mergeSort(r));
return q;
}
private static int[] merge(int[]a, int[]b) {
int length = a.length + b.length;
int[] c = new int[length];
int p = 0;
while (a.length > 0 && b.length > 0) {
if (a[0] < b[0]) {
c[p++] = a[0];
a = tail(a);
} else {
c[p++] = b[0];
b = tail(b);
}
}
while (a.length > 0) {
c[p++] = a[0];
a = tail(a);
}
while (b.length > 0) {
c[p++] = b[0];
b = tail(b);
}
return c;
}
private static int[] tail(int[] a) {
int[] t = new int[a.length - 1];
for (int i = 0; i < t.length; i++) {
t[i] = a[i + 1];
}
return t;
}
}
Actually you have a problem with the auxiliary method merge().
I strongly recommend you to take this as an opportunity to practice systematic testing of your methods. Consider that we all constantly make mistakes when we write programs, and spotting errors to correct them is a real part of the job.
What make it easier, is to anticipate over this matter of fact : sh*t happens. And take time to write down some test cases, with input data and expected results.
int[] empty = {};
int [] r1 = merge(empty, empty);
System.out.println("Result should be empty\n");
printArray(r1);
int [] oneElement = { 23 };
int [] r3 = merge(oneElement, empty);
System.out.println("Result should be [23]\n");
printArray(r2);
...
So you have automated tests (we're all too lazy to do it by hand every time after the 35th modification of the codeĀ°.
This will lead you to "unit tests"....

Java Matrices - Transpose & Sum

I am working on a Matrix program on eclipse and I am currently stuck on 2 methods in which I thought were the most simplest of all. The first method that I am working on is to take the sum of 2 different 2D arrays from the #Test cases and returning the sum in a new 2D array. I already have an 2D array instance variable. The reason I am stuck is because the of the parameter in the method. The parameter doesn't give any variable other than the class (Matrix) and the variable (other). So I was wondering how to go about getting this method started and most importantly returning the sum array.
The other method I am stuck on is the transpose method where you must flip the rows and columns of the given 2D array. I know I must create a temp 2D array in order to store the content back into the original 2D array but for some reason it is not passing the test cases. If someone could please help me with these two methods, it would be much appreciated.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;
private int theRow;
private int theCol;
public Matrix(int[][] arrayOfArrays) {
// TODO Auto-generated constructor stub
array = new int[arrayOfArrays.length][arrayOfArrays[0].length];
for (int r = 0; r < arrayOfArrays.length; r++) {
for (int c = 0; c < arrayOfArrays[r].length; c++) {
array[r][c] = arrayOfArrays[r][c];
}
}
}
public int get(int row, int column) {
return array[row][column];
}
public int getNumberOfRows() {
int nRows = array.length;
return nRows;
}
public int getNumberOfColumns() {
int nCols = array[0].length;
return nCols;
}
public String toString() {
String res = "";
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[r].length; c++)
res = res + array[r][c];
}
return res;
}
public Matrix sum(Matrix other) {
return sum;
}
public void scalarMultiply(int scalar) {
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[0].length; c++) {
array[r][c] = array[r][c] * scalar;
}
}
}
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
int temp;
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
array[r][c] = array[c][r];
array[c][r] = transpose[c][r];
}
}
}
//The test cases for sum method and transpose method
#Test
public void testSum() {
int[][] a1 = { { 1, 2, 3 },
{ 5, 6, 7 } };
Matrix a = new Matrix(a1);
int[][] a2 = { { -2, -2, -2 },
{ 4, 4, 4 } };
Matrix b = new Matrix(a2);
Matrix c = a.sum(b);
assertEquals(-1, c.get(0, 0));
assertEquals(0, c.get(0, 1));
assertEquals(1, c.get(0, 2));
assertEquals(9, c.get(1, 0));
assertEquals(10, c.get(1, 1));
assertEquals(11, c.get(1, 2));
}
#Test
public void testTranspose() {
int[][] a1 = { { 1, 3, 5 },
{ 2, 4, 6 } };
Matrix a = new Matrix(a1);
a.transpose();
assertEquals(1, a.get(0, 0));
assertEquals(2, a.get(0, 1));
assertEquals(3, a.get(1, 0));
assertEquals(4, a.get(1, 1));
assertEquals(5, a.get(2, 0));
assertEquals(6, a.get(2, 1));
}
You need change the dimensions, for example, 2x3 -> 3x2.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;// remove this
private int theRow;// remove this
private int theCol;// remove this
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
}
}
array = transpose;
}
}

Finding intersection of two sorted arrays in Java

public class intersect {
public static void find(int[] a, int[] b, int[] acc)
{
int position = 0;
for (int j = 0; j < a.length; j++) {
for (int k = 0; k<b.length; k++) {
if (a[j] == b[k]) {
acc[position] = b[k];
position++;
}
}
}
System.out.println(java.util.Arrays.toString(acc));
}
public static void main (String[] s)
{
int[] acc = new int[2];
int[] a = {1,2,3};
int[] b = {2,3,4};
find(a, b, acc);
}
}
I have written the above code to solve the problem.
But if you see, the function is very limited because I have to change the length of the acc every time. That means I have to know how many elements are intersecting. In this case, the array {1,2,3} and {2,3,4} have {2,3} in common, so the length of the acc would be 2.
I am sure there are millions of ways of tackling this problem, but I cannot seem to think of a way of fixing this.
Please help!
If your professor wants you to use arrays, you can use the following method:
public static int[] resize(int[] arr)
{
int len = arr.length;
int[] copy = new int[len+1];
for (int i = 0; i < len; i++)
{
copy[i] = arr[i];
}
return copy;
}
This will increase the size of the array by 1. You can use that instead. By the way, you're not using the fact that they're sorted in your find() method. What you should do is this:
public static void find(int[] a, int[] b, int[] acc)
{
int a_index = 0, b_index = 0, acc_index = -1;
int a_element, b_element;
while (a_index < a.length && b_index < b.length)
{
a_element = a[a_index]; b_element = b[b_index];
if (a_element == b_element)
{
acc = resize(acc);
acc[++acc_index] = a_element;
a_index++; b_index++;
} else if (b_element < a_element) {
b_index++;
} else {
a_index++;
}
}
System.out.println(java.util.Arrays.toString(acc));
}
This method is more efficient now. Working example.
To find intersection of 2 sorted arrays, follow the below approach :
1) Use two index variables i and j, initial values with 0
2) If array1 is smaller than array2 then increment i.
3) If array1 is greater than array2 then increment j.
4) If both are same then print any of them and increment both i and j.
check this link for more information
https://www.geeksforgeeks.org/union-and-intersection-of-two-sorted-arrays-2/
public class FindIntersection {
static void findInterSection(int array1[], int array2[], int array1NoOfElements, int
array2NoOfElements) {
int i = 0, j = 0;
while (i < array1NoOfElements && j < array2NoOfElements) {
if (array1[i] < array2[j]) {
i++;
} else if (array2[j] < array1[i]) {
j++;
}
// if both array elements are same
else {
System.out.println(array2[j++] + " ");
i++;
}
}
}
public static void main(String[] args)
{
int myFirstArray[] = { 1, 2, 4, 5, 5 };
int mySecondArray[] = { 2, 3, 5, 7 };
int m = myFirstArray.length;
int n = mySecondArray.length;
findInterSection(myFirstArray, mySecondArray, m, n);
}
}
Make your intersection array's size the size of the smaller of your original arrays. That way, you won't ever have to increase it's capacity.
Then you can use Arrays.copy to transfer your results into an appropriately sized array.
Not sure if this is the best solution, but you don't need to hard-code the size of the intersection ahead of time (which is one thing you were concerned about).
As you iterate through both arrays, you can add elements found in both sets to a StringBuilder (along with some delimiter, I used a comma in the example below). Once you're finished, you can call toString() & then split() using the delimiter afterwards to get a String[]. At that point, you can put convert those String objects to int primitives & return an int[].
public class Scratch {
public static void main(String[] s) {
int[] a = {1, 2, 3};
int[] b = {2, 3, 4};
int[] intersection = findIntersection(a, b);
System.out.println(Arrays.toString(intersection));
}
public static int[] findIntersection(int[] a, int[] b) {
StringBuilder intersectionStringBuilder = new StringBuilder();
for (int j = 0; j < a.length; j++) {
for (int k = 0; k < b.length; k++) {
if (a[j] == b[k])
intersectionStringBuilder.append(a[j] + ",");
}
}
String[] intersectionStringArray = intersectionStringBuilder.toString().split(",");
int[] intersection = new int[intersectionStringArray.length];
for (int current = 0; current < intersectionStringArray.length; current++) {
intersection[current] = Integer.parseInt(intersectionStringArray[current]);
}
return intersection;
}
}
for(int i=0;i<arr1.length;i++){
for(int j=0;j<arr2.length;j++){
if(arr1[i]==arr2[j] && !index.contains(j)){
list.add(arr1[i]);
index.add(j);
break;
}
}
}
int result[]=new int[list.size()];
int k=0;
for(int i:list){
result[k]=i;
k++;
}
for(int i=0;i<result.length;i++){
System.out.println(result[i]);
}
return result;
}

Categories