java.lang.StackOverflowError in MergeSort - java

public class MergeSort
{
public static double[] MergeSort(double[] a){
if(a.length < 1){
return new double[0];
}
else if(a.length == 1){
return a;
}
else{
double[] l = Teiler(a, false);
double[] r = Teiler(a, true);
return Fueger(MergeSort(l), MergeSort(r));
}
}
...
}
public static double[] Fueger(double[] a, double[] b):
returns an array of doubles containing all numbers from a and b in correct order.
public static double[] Teiler(double[] a, boolean l):
returns half of the elements (the first half, if l is false, second half, if l is true)
Fueger and Teiler work perfectly well, but MergeSort always gives java.lang.StackOverflowError, even though the recursion should be terminates as soon as the array is empty or just contains one element.
What is the problem?
Thanks for your help
Here is Fueger:
public static double[] Fueger(double[] a, double[] b){
double[] hilf = new double[a.length + b.length];
int i = 0;
while((a.length != 0) && (b.length != 0)){
if(a[0] < b[0]){
hilf[i] = a[0];
a = Weg(a);
}
else{
hilf[i] = b[0];
b = Weg(b);
}
i++;
}
if(a.length != 0){
for(double x : a){
hilf[i] = x;
a = Weg(a);
i++;
}
}
if(b.length != 0){
for(double x : b){
hilf[i] = x;
b = Weg(b);
i++;
}
}
return hilf;
}
Teiler:
public static double[] Teiler(double[] a, boolean r){
double[] hilf;
int x = 0;
if(r == false){
hilf = new double[(int) a.length / 2];
for(int i = 0; i < a.length / 2; i++){
hilf[x] = a[i];
i ++;
}
}
else{
hilf = new double[(int) (a.length / 2) + 1];
for(int i = a.length / 2; i < a.length; i++){
hilf[x] = a[i];
i ++;
}
}
return hilf;
}

The problem is in the Teiler method. Consider a list of length 2, the else branch creates a list of length 2 rather than 1 (even though it fills only the first element). Consequently, trapping the recursion in an endless loop. You can easily fix this issue by adding the last element only if the length is odd:
public static double[] Teiler(double[] a, boolean r){
double[] hilf;
int x = 0;
if(r == false){
hilf = new double[(int) a.length / 2];
for(int i = 0; i < a.length / 2; i++){
hilf[x] = a[i];
i ++;
}
} else{
hilf = new double[(int) (a.length / 2) + (a.length % 2)];
for(int i = a.length / 2; i < a.length; i++){
hilf[x] = a[i];
i ++;
}
}
return hilf;
}

Related

Minimum time required to rot all oranges

Given a matrix of dimension r*c where each cell in the matrix can have values 0, 1 or 2 which has the following meaning:
0 : Empty cell
1 : Cells have fresh oranges
2 : Cells have rotten oranges
So, we have to determine what is the minimum time required to rot all oranges. A rotten orange at index [i,j] can rot other fresh orange at indexes [i-1,j], [i+1,j], [i,j-1], [i,j+1] (up, down, left and right) in unit time. If it is impossible to rot every orange then simply return -1.
Input:
The first line of input contains an integer T denoting the number of test cases. Each test case contains two integers r and c, where r is the number of rows and c is the number of columns in the array a[]. Next line contains space separated r*c elements each in the array a[].
Here is the Code I have written
class GFG {
public static boolean isSafe(int[][] M, boolean[][] visited, int i, int j) {
int R = M.length;
int C = M[0].length;
return (i >= 0 && i < R && j >= 0 && j < C && (!visited[i][j]) && M[i][j] != 0);
}
public static int findMinDist(int[][] M, boolean[][] visited, int i, int j, int dist) {
if (M[i][j] == 2)
return dist;
int[] x_pos = { 1, -1, 0, 0 };
int[] y_pos = { 0, 0, -1, 1 };
visited[i][j] = true;
int min = Integer.MAX_VALUE;
for (int k = 0; k < 4; k++) {
if (isSafe(M, visited, i + x_pos[k], j + y_pos[k]))
min = Math.min(min, findMinDist(M, visited, i + x_pos[k], j + y_pos[k], dist + 1));
}
return min;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int t = 0; t < T; t++) {
int R = sc.nextInt();
int C = sc.nextInt();
int[][] M = new int[R][C];
boolean[][] visited = new boolean[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
M[i][j] = sc.nextInt();
}
}
int[][] time = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (M[i][j] == 1)
time[i][j] = findMinDist(M, new boolean[R][C], i, j, 0);
}
}
int maxTime = Integer.MIN_VALUE;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
maxTime = Math.max(time[i][j], maxTime);
}
}
System.out.println(maxTime == Integer.MAX_VALUE ? -1 : maxTime);
}
}
}
I am trying to find minimum distance of 2 from each 1.
It is not working for test case
Input:
1
2 5
1 1 1 1 1 0 2 1 1 1
Its Correct output is:
4
And My Code's output is:
6
Please suggest what's wrong with the code.
Start by creating a matrix to store the times the oranges rot. You can initialize all slots with -1. You will use BFS but you won't need a "marked" matrix, because the times the oranges rot will already be enough to tell you if a slot has been visited or not.
Iterate through the original matrix. When you find a value 2, do a BFS starting there to rot the fresh oranges. This BFS should also state the time when each orange is rot and you must always keep the smallest time. If the orange being looked at the moment was already rotten at time t1 and you've just got there in time t2, where t2 < t1, pretend this orange is fresh and put it into the BFS queue like so.
After finishing it, iterate through the matrix of times and return the biggest value found.
class Pair {
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public int x;
public int y;
}
public class Solution {
public static boolean isSafe(int x, int y, int r, int c) {
return (x >= 0) && (x < r) && (y >= 0) && (y < c);
}
public static boolean isFreshOrageLeft(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 1)
return true;
}
}
return false;
}
public static int orangesRotting(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
int count = 0;
boolean flag = false;
Queue<Pair> q = new LinkedList<>();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 2)
q.add(new Pair(i, j));
}
}
q.add(new Pair(-1, -1));
while (!q.isEmpty()) {
while (q.peek().x != -1 && q.peek().y != -1) {
Pair p = q.poll();
int leftX = p.x - 1;
int leftY = p.y;
if (isSafe(leftX, leftY, r, c) && grid[leftX][leftY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[leftX][leftY] = 2;
q.add(new Pair(leftX, leftY));
}
int rightX = p.x + 1;
int rightY = p.y;
if (isSafe(rightX, rightY, r, c) && grid[rightX][rightY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[rightX][rightY] = 2;
q.add(new Pair(rightX, rightY));
}
int upX = p.x;
int upY = p.y + 1;
if (isSafe(upX, upY, r, c) && grid[upX][upY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[upX][upY] = 2;
q.add(new Pair(upX, upY));
}
int downX = p.x;
int downY = p.y - 1;
if (isSafe(downX, downY, r, c) && grid[downX][downY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[downX][downY] = 2;
q.add(new Pair(downX, downY));
}
}
flag = false;
q.poll();
if (!q.isEmpty())
q.add(new Pair(-1, -1));
}
return isFreshOrageLeft(grid)?-1:count;
}
public static void main(String[] args) {
int[][] grid = {{2,2,0,1}};
System.out.println(orangesRotting(grid));
}
}

What is time complexity of this recursive function?

public static int[] index(int input[],int x,int i){
if (i==0) {
if (input[i]==x)
return new int[] {0};
else
return new int[] {};
}
int[] c = index(input, x, i-1);
if (input[i] == x) {
int len = c.length + 1;
int[] a = new int[len];
int j;
for (j = 0; j <= c.length - 1; j++)
a[j] = c[j];
a[j] = i; // j++
return a;
}
return c;
}
What is time complexity of this recursive function which returns all indices of occurrence of an element x in an input array?

Union or intersection of Java Sets

What is the simplest way to make a union or an intersection of Sets in Java? I've seen some strange solutions to this simple problem (e.g. manually iterating the two sets).
The simplest one-line solution is this:
set1.addAll(set2); // Union
set1.retainAll(set2); // Intersection
The above solution is destructive, meaning that contents of the original set1 my change.
If you don't want to touch your existing sets, create a new set:
var result = new HashSet<>(set1); // In Java 10 and above
Set<Integer> result = new HashSet<>(set1); // In Java < 10
result.addAll(set2); // Union
result.retainAll(set2); // Intersection
While guava for sure is neater and pretty much standard, here's a non destructive way to do union and intersect using only standard Java
Set s1 = Set.of(1,2,3);
Set s2 = Set.of(3,4,5);
Set union = Stream.concat(s1.stream(),s2.stream()).collect(Collectors.toSet());
Set intersect = s1.stream().filter(s2::contains).collect(Collectors.toSet());
You can achieve this using Google's Guava library. The following explanation is given below with the help of an example:
// Set a
Set<String> a = new HashSet<String>();
a.add("x");
a.add("y");
a.add("z");
// Set b
Set<String> b = new HashSet<String>();
b.add("x");
b.add("p");
b.add("q");
Now, Calculating Intersection of two Set in Java:
Set<String> intersection = Sets.intersection(a, b);
System.out.printf("Intersection of two Set %s and %s in Java is %s %n",
a.toString(), b.toString(), intersection.toString());
Output: Intersection of two Set [z, y, x] and [q, p, x] in Java is [x]
Similarly, Calculating Union of two Set in Java:
Set<String> union = Sets.union(a, b);
System.out.printf("Union of two Set %s and %s in Java is %s %n",
a.toString(), b.toString(), union.toString());
Output: Union of two Set [z, y, x] and [q, p, x] in Java is [q, p, x, z, y]
You can read more about guava library at https://google.github.io/guava/releases/18.0/api/docs/
In order to add guava library to your project, You can see https://stackoverflow.com/a/4648947/8258942
import java.util.*;
public class sets {
public static void swap(int array[], int a, int b) { // Swap function for sorting
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
public static int[] sort(int array[]) { // sort function for binary search (Selection sort)
int minIndex;
int j;
for (int i = 0; i < array.length; i++) {
minIndex = i;
for (j = i + 1; j < array.length; j++) {
if (array[minIndex] > array[j])
minIndex = j;
}
swap(array, minIndex, i);
}
return array;
}
public static boolean search(int array[], int search) { // Binary search for intersection and difference
int l = array.length;
int mid = 0;
int lowerLimit = 0, upperLimit = l - 1;
while (lowerLimit <= upperLimit) {
mid = (lowerLimit + upperLimit) / 2;
if (array[mid] == search) {
return true;
} else if (array[mid] > search)
upperLimit = mid - 1;
else if (array[mid] < search)
lowerLimit = mid + 1;
}
return false;
}
public static int[] append(int array[], int add) { // To add elements
int newArray[] = new int[array.length + 1];
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
newArray[array.length] = add;
newArray = sort(newArray);
return newArray;
}
public static int[] remove(int array[], int index) { // To remove duplicates
int anotherArray[] = new int[array.length - 1];
int k = 0;
if (array == null || index < 0 || index > array.length) {
return array;
}
for (int i = 0; i < array.length; i++) {
if (index == i) {
continue;
}
anotherArray[k++] = array[i];
}
return anotherArray;
}
public static void Union(int A[], int B[]) { // Union of a set
int union[] = new int[A.length + B.length];
for (int i = 0; i < A.length; i++) {
union[i] = A[i];
}
for (int j = A.length, i = 0; i < B.length || j < union.length; i++, j++) {
union[j] = B[i];
}
for (int i = 0; i < union.length; i++) {
for (int j = 0; j < union.length; j++) {
if (union[i] == union[j] && j != i) {
union = remove(union, j); // Removing duplicates
}
}
}
union = sort(union);
System.out.print("A U B = {"); // Printing
for (int i = 0; i < union.length; i++) {
if (i != union.length - 1)
System.out.print(union[i] + ", ");
else
System.out.print(union[i] + "}");
}
}
public static void Intersection(int A[], int B[]) {
int greater = (A.length > B.length) ? (A.length) : (B.length);
int intersect[] = new int[1];
int G[] = (A.length > B.length) ? A : B;
int L[] = (A.length < B.length) ? A : B;
for (int i = 0; i < greater; i++) {
if (search(L, G[i]) == true) { // Common elements
intersect = append(intersect, G[i]);
}
}
for (int i = 0; i < intersect.length; i++) {
for (int j = 0; j < intersect.length; j++) {
if (intersect[i] == intersect[j] && j != i) {
intersect = remove(intersect, j); // Removing duplicates
}
}
}
System.out.print("A ∩ B = {"); // Printing
for (int i = 1; i < intersect.length; i++) {
if (i != intersect.length - 1)
System.out.print(intersect[i] + ", ");
else
System.out.print(intersect[i] + "}");
}
}
public static void difference(int A[], int B[]) {
int diff[] = new int[1];
int G[] = (A.length > B.length) ? A : B;
int L[] = (A.length < B.length) ? A : B;
int greater = G.length;
for (int i = 0; i < greater; i++) {
if (search(L, G[i]) == false) {
diff = append(diff, G[i]); // Elements not in common
}
}
for (int i = 0; i < diff.length; i++) {
for (int j = 0; j < diff.length; j++) {
if (diff[i] == diff[j] && j != i) {
diff = remove(diff, j); // Removing duplicates
}
}
}
System.out.println("Where A is the larger set, and B is the smaller set.");
System.out.print("A - B = {"); // Printing
for (int i = 1; i < diff.length; i++) {
if (i != diff.length - 1)
System.out.print(diff[i] + ", ");
else
System.out.print(diff[i] + "}");
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the operation");
String operation = sc.next().toLowerCase();
System.out.println("Enter the length of the first set.");
int l1 = sc.nextInt();
System.out.println("Enter the length of the second set.");
int l2 = sc.nextInt();
int A[] = new int[l1];
int B[] = new int[l2];
System.out.println("Enter the elements of the first set.");
System.out.print("A = ");
for (int i = 0; i < l1; i++) {
A[i] = sc.nextInt();
}
System.out.println("Enter the elements of the second set.");
System.out.print("B = ");
for (int i = 0; i < l2; i++) {
B[i] = sc.nextInt();
}
A = sort(A); // Sorting the sets before passing
B = sort(B);
sc.close();
switch (operation) {
case "union":
Union(A, B);
break;
case "intersection":
Intersection(A, B);
break;
case "difference":
difference(B, A);
break;
default:
System.out.println("Invalid Operation");
}
}
}
When I think of union and intersection, it is in the first loop an operation on sets, i.e. a map
            Set<T>  x  Set<T>  →  Set<T>Not clear, why it would appear in Java design that shirtsleeved.
static <T> Set<T> union(Set<T> a, Set<T> b)
{
Set<T> res = new HashSet<T>(a);
res.addAll(b);
return res;
}
static <T> Set<T> intersection(Set<T> a, Set<T> b)
{
Set<T> res = new HashSet<T>(a);
res.retainAll(b);
return res;
}

I am trying to write a quickSort method as part of an assignment, but I keep getting a StackOverflow error in Java

This is the code for my sorting attempt. After running for about ten minutes in Eclipse's debugger mode, I got a lot of StackOverFlow errors. This was my output display:
Exception in thread "main" java.lang.StackOverflowError
at TestSorter.Tester.sort(Tester.java:6)
... (x112 repetitions of at TestSorter.Tester.sort(Tester.java:49))
at TestSorter.Tester.sort(Tester.java:49)
public static int[] sort(int[] a) {
int prod = (a.length)/2, b = lessThan(a, prod), c = greaterThan(a, prod), d = equalTo(a, prod);
int[] first, last, mid;
first = new int[b];
last = new int[c];
mid = new int[d];
int[] fina = new int[a.length];
int f = 0, l = 0, m = 0;
if (isSorted(a))
return a;
for (int x = 0; x < a.length; x++) {
if (a[x] < prod) {
first[f] = a[x];
f++;
}
else if (a[x] > prod) {
last[l] = a[x];
l++;
}
else if (a[x] == prod) {
mid[m] = a[x];
m++;
}
}
if (m == a.length)
return a;
first = sort(first);
last = sort(last);
for (int x = 0; x < b; x++) {
fina[x] += first[x];
}
for (int x = 0; x < d; x++) {
fina[x + b] = mid[x];
}
for (int x = 0; x < c; x++) {
fina[x + b + c] = last[x];
}
return fina;
}
My support methods are as follows:
private static int lessThan(int[] a, int prod) {
int less = 0;
for (int x = 0; x < a.length; x++) {
if (a[x] < prod) {
less++;
}
}
return less;
}
private static int greaterThan(int[] a, int prod) {
int greater = 0;
for (int x = 0; x < a.length; x++) {
if (a[x] > prod) {
greater++;
}
}
return greater;
}
private static int equalTo(int[] a, int prod) {
int equal = 0;
for (int x = 0; x < a.length; x++) {
if (a[x] == prod) {
equal++;
}
}
return equal;
}
private static boolean isSorted(int[] a) {
for (int x = 0; x < a.length - 1; x++) {
if (a[x] > a[x + 1])
return false;
}
return true;
}
Presumably the trouble is that your "prod" is not within the domain of your array. Thus either "first" or "last" is the same size as the input array, and you have an infinite recursion. Try setting prod to be an element in the array you are trying to sort.
THREE POINTS:
The pord should be the mid-element of the array, NOT the half of the array's length.
So, it should be prod =a[(a.length) / 2],
NOT prod =(a.length) / 2
If the array first only have 1 element, it does not need invoke the method sort any more.
Also the last.
So, add if statement:
if (1 < first.length) {
first = sort(first);
}
When you append the element of last to fina, the index should be x+b+d, it means first elements(b) + mid elements(d). NOT x+b+c.
So, change fina[x + b + c] = last[x]; to fina[x + b + d] = last[x];
Well, the method sort maybe like this:
public static int[] sort(int[] a) {
int prod =a[(a.length) / 2], b = lessThan(a, prod), c = greaterThan(a,
prod), d = equalTo(a, prod);
int[] first, last, mid;
first = new int[b];
last = new int[c];
mid = new int[d];
int[] fina = new int[a.length];
int f = 0, l = 0, m = 0;
if (isSorted(a) )
return a;
for (int x = 0; x < a.length; x++) {
if (a[x] < prod) {
first[f] = a[x];
f++;
} else if (a[x] > prod) {
last[l] = a[x];
l++;
} else if (a[x] == prod) {
mid[m] = a[x];
m++;
}
}
if (m == a.length)
return a;
if (1 < first.length) {
first = sort(first);
}
if (1 < last.length) {
last = sort(last);
}
for (int x = 0; x < b; x++) {
fina[x] += first[x];
}
for (int x = 0; x < d; x++) {
fina[x + b] = mid[x];
}
for (int x = 0; x < c; x++) {
fina[x + b + d] = last[x];
}
return fina;
}

Feige Fiat Shamir Implementation

I'm implementing the Fiege Fiat Shamir Identification Scheme in Java, and I'm pretty sure that it's fine math-wise. (I've checked many many times) But it never works (when check is called, it is almost always false, even when called with numbers that should work). I've gotten it to work before without sequences, (k value of 1), but now it doesn't work. Help!
public class ZKPTimeTrials {
public static int gcd(int p, int q) {
if (q == 0) return p;
else return gcd(q, p % q);
}
public static int randomR(int min, int max) {
Random randgen = new Random();
return randgen.nextInt((max - min) + 1) + min;
}
public static int getRandomCoprime(int n) {
int result = n;
while (gcd(n, result) != 1) {
result = randomR(2, n-1);
}
return result;
}
public static int[] makeSi(int k, int n) {
int[] result = new int[k];
for(int i = 0; i < result.length; i++) {
result[i] = getRandomCoprime(n);
}
return result;
}
public static int[] makeVi(int[] si, int n) {
int[] result = new int[si.length];
for(int i = 0; i < result.length; i++) {
result[i] = (si[i] * si[i]) % n;
}
return result;
}
public static int[] makeEi(int k) {
int[] result = new int[k];
for(int i = 0; i < k; i++) {
result[i] = randomR(0, 1);
}
return result;
}
public static int makeY(int r, int[] ei, int[] si, int n) {
int result = r;
for(int i = 0; i < si.length; i++) {
result *= (int) Math.pow(si[i], ei[i]);
}
return result % n;
}
public static boolean check(int n, int x, int y, int[] ei, int[] vi) {
int signBit = ZKPTimeTrials.randomR(0, 1);
if(signBit == 0) {
signBit = -1;
}
int shouldY = x * signBit;
for(int i = 0; i < vi.length; i++) {
shouldY *= (int) Math.pow(vi[i], ei[i]);
}
return ((y * y) % n) == shouldY % n;
}
public static void main(String args[]) {
int n = 71 * 7;
int t = 50;
int k = 10;
int[] si = makeSi(k, n);
int[] vi = makeVi(si, n);
int r = randomR(2, n-1);
int ei[] = makeEi(k);
int s = randomR(0, 1);
if(s == 0) {
s = -1;
}
int x = (s * r * r) % n;
int y = makeY(r, ei, si, n);
for(int i = 0; i < si.length; i++) System.out.print(ei[i] + " ");
System.out.println();
for(int i = 0; i < si.length; i++) System.out.print(si[i] + " ");
System.out.println(check(n, x, y, ei, vi));
}
}
The first problem is an integer overflow in makeY and check: In both functions 'result' is very likely to overflow, because you build the product first and reduce modulo n afterwards. Try to reduce mod n after every multiplication to keep 'result' small.
For example in makeY, write:
int result = r % n;
for (int i = 0; i < si.length; i++) {
if (ei[i] == 1)
result = (result * si[i]) % n;
}
return result;
(I also removed Math.pow() to make it more readable and efficient, but this was not an error.)
The second problem is the logic of your check function: The signBit variable is not needed, but instead you should check if y*y is equal to shouldY or -shouldY.
public static boolean check(int n, int x, int y, int[] ei, int[] vi) {
int shouldY = x % n;
for (int i = 0; i < vi.length; i++) {
if (ei[i] == 1)
shouldY = (shouldY * vi[i]) % n;
}
return (y*y - shouldY) % n == 0 || (y*y + shouldY) % n == 0;
}
With these small corrections i managed to get your code running. Hope it helps...

Categories