Stack Overflow Error in java with small input set - java

I am trying to write quick sort in java. But getting a stack over flow error for very small set of inputs. In the createArray function I am taking input by the Scanner object.
Please somebody help me in this.
public class quickSort {
static int[] ar;
int number;
public static void main(String args[]) {
CreatingArray ca = new CreatingArray();
ar = ca.createArray();
ca.printArray(ar);
int len = ar.length;
sort(0,(len-1));
System.out.println("");
System.out.println("Array after QuickSort:");
ca.printArray(ar);
}
public static void sort(int l,int h) {
int i=l;
int j=h;
int temp =0;
int pivot = ar[(l + (l+h)/2)];
while(i <= j) {
while(ar[i] < pivot) {
i++;
}
while(ar[j] > pivot) {
j--;
}
if (i<=j) {
temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
i++;
j--;
}
}
if(l<j){
sort(l,j);
}
if(i<h) {
sort(i,h);
}
}
}

int pivot = ar[(l + (l+h)/2)];
This line is wrong. It only gets the center point when l == 0. If, say, l == 4 && h == 7 (e.g. the upper half of an 8-element array), you get 4 + (4+7)/2 which is 9 and thus outside the bounds. You really want l + (h-l+1)/2.
The first thing that can happen because of this is ArrayIndexOutOfBoundsException, but you never get that because you always recurse on the lower partition first and run into the second problem. Swap the two ifs at the end of the function to see this in action.
The second thing that can happen is that, because pivot is not actually an element in the range [i, j], the element search at the start of the loop can go crazy. In particular, pivot could be a very small value that is smaller than any in the range. The i search will terminate immediately (leaving i == l the way it started), while the j search will run way beyond i, which means the if won't be entered either, i still doesn't change, and the main loop terminates. Because i is unchanged, i<h is still true (assuming l<h was), and you enter the recursive call with exactly the same arguments you just had, which means the next call will do exactly the same thing as the current one, ending in infinite recursion.

I think your recursive calls don't end... debug your code with very small input - say 3 numbers... check when and how sort() is being called..

Related

finding a possible combination of 2 adjacent array elements of an alternately sorted array

as per usual, I've searched around google and here for an answer, but couldn't find anything that helps me. Keep in mind it's NOT for homework, I'm studying for a test and struggling to complete the answer for this question.
There's an alternately sorted array, meaning, the even index elements are sorted and the odd index elements are sorted as well (from smallest to biggest numebr).
For example:
int a[] = {1,2,5,3,6,10,9};
Now, the question asks to write a boolean method, that receives an array and a number, x, and returns true if the number is a possible combo of 2 adjacent "tiles" and false if not. For example:
x = 9;
FindX(a,9) -> true;
a[3](3) + a[4](6) = 9.
I've written my method, and it seems to work with a number that IS a possible combo, but when it should return false it gets stuck when the number is in the range of 2 possible combos.
public static boolean FindX(int a[], int x){
if (a.length==1) { // The question specifies if it's an array with 1 element is should return false.
return false;
}
int i=(a.length-1)/2; // The middle index
int i2=i+1; // The adjacent index
for (; i>=0 && i2<a.length;){ // beginning of loop, if either index is out of bounds, terminates look
if (a[i]+a[i2]==x) { // once you reach the proper index (when x is within) it returns true
return true;
}
else if (a[i]+a[i2]>x){ // if x is smaller than current combo, make the new index in the new bounds
i = (i/2)+1;
i2 = i+1;
}
else if (a[i]+a[i2]<x){ // same as above boolean, but opposite situation
i = (i2+a.length)/2;
i2 = i+1;
}
}
return false;
}
Whenever I input a possible combination, it does work. But if for example I put 14, which i between 9 (=a[3](3) + a[4](6)) and 16 (=a[4](6) + a[5](10)) it loops forever and I can't think of a proper way to exit when that occurs. If the number is out of possible combos but not in the range, it does return false, but for in-between numbers I am stuck.
Answer must be a efficient as possible in both memory and time complexity.
Thanks in advance.
You implemented a binary search incorrectly: i and i2 point to the middle and "middle plus one," while you should be keeping one index pointing at the beginning and one to the end of the valid range.
To implement this correctly, first consider an imaginary array composed of sums of adjacent items:
int a[] = {1,2,5,3,6,10,9};
int s[] = { 3,7,8,9,16,19};
This imaginary array would have a.length-1 elements, and it would be sorted in ascending order.
This observation replaces two alternately sorted "inconvenient" sequences with a single fully sorted "convenient" sequence. You can find an answer to your problem by searching this sequence using binary search.
You don't need to create this array explicitly. Write a classic binary search implementation, for indexes 0 through a.length-2, inclusive, but instead of writing s[mid] < x write a[mid]+a[mid+1] < x.
As per dasblinkenlight suggestion, A simple binary search implementation can cater this requirement. it is efficient
public class combo {
public static void main(String[] args){
int a[] = {1,2,5,3,6,10,9};
System.out.println(FindX(a, 14));
}
public static boolean FindX(int a[], int x){
if (a.length==1) { // The question specifies if it's an array with 1 element is should return false.
return false;
}
int mid = a.length/2;
int toSearchFrom = 0;
int toSearchTill = 0;
if(a[mid-1]+a[mid] < x){
toSearchFrom = mid;
toSearchTill = a.length - 1;
} else if(a[mid-1]+a[mid] > x){
toSearchFrom = 0;
toSearchTill = mid - 1;
}
for(int i=toSearchFrom; i < toSearchTill; i++){
if(a[i] + a[i+1] == x){
return true;
}
}
return false;
}
}
Sample Input 1 - 19 Output = true
Sample Input 2 - 14 Output = false
Sample Input 3 - 3 Output = true

Time complexity for a recursion inside for loop java

Hello i encountered this problem. I try to solve this for three days now with the help of several stack overflow posts, google and youtube but i can´t solve this.
My Question is. How do i get T(N) = ? for perm(1). I guess it is somehow O(n^2) or even worse because of the following. My for-loop depends on a variable n and my recursion inside takes n+1 so this would be n*(n+1) ~ n^2. But how do i get through this program and proove this? I know i can ignore all constant factors like addition etc but i would be nice if someone takes the time to explain every time-unit-cost what ever in the code and sum it up until we have a recursiv equation.
To get every single permutation we change perm(1) to perm(0).
1) How many calls do we have if we permute n-Numbers
2) How many calls are being omitted in average for a single permutation if n gets very big.
Explanation. We give this program n-Numbers to permute. If we want to permute the 0 as well, we call perm(0), else we call perm(1).
private void perm(int i) { // permute from index i; 1 or 0(all permuts).
if (i >= max) put(); // one permutation finished, max = n-1
else {
for (int j = i; j <= max; j++) { // everyone in front
swap(i, j); // swap
perm(i + 1); // and recursion
}
int h = a[i]; // restore Array
System.arraycopy(a, i + 1, a, i, max - i); // shift left
a[max] = h;
}
} // end perm
private void swap(int i, int j) { // swap a[i] <-> a[j]
if (i != j) {
int h = a[i];
a[i] = a[j];
a[j] = h;
}
} // end swap
private synchronized void put() { // give over to array
mayread = true; // read a (array)
notify(); // notify the other Thread
try {
if (a != null)
while (mayread) wait(); // non busy waiting
} catch (InterruptedException e) {
}
} // end put
And my final question. What the heck happens when we are inside the for-loop and we call swap(1,1), as j=i, or swap(2,2) and after that the recursion.
swap is O(1).
perm executes a loop of max-i+1 iterations, then, on each iteration executes perm(i+1). Then, after all, it does an arraycopy of max-i items.
Let's call max as n.
perm(1) executes the loop n times
perm(2) executes the loop n-1 times
perm(3) executes the loop n-2 times
and so on...
This leads to a n*(n-1)*(n-2)*...*1 iterations. O(n!)
Also, swap(1, 1) does nothing.

Sorting an array recursively in Java with even numbers appearing in front of array.

I'm using a method to sort out an array with even numbers coming out in the front and odd numbers in the back of the array. My assignment dictates that i accomplish this using recursion. When I try to print the sorted out array it just prints out the array unsorted. What am i doing wrong?
The left variable starts at index 0 and the right variable starts at the end of the index. They are then both compared, if left is an odd number and right is an even number then they swap values. If left turns out to be an even number then no swap takes place and it points at the next index in the array. If right turns out to be an odd number then no swap takes place and it points at the next index in the array. It does this until all the even numbers are on the right of the array.
I'm getting a
"Exception in thread "main" java.lang.StackOverflowError".
import java.util.*;
public class Problem2{
//i=left
//j=right
//first i tried to shift the whole thing
//have all even numbers pop to the front of array when even
public static int[] callme(int[] arry, int left, int right){
int temp;
if(left>=right) //base case, return array
return arry;
else if(arry[left]%2!=0 && arry[right]%2==0){//if match, do the swap
temp=arry[left];
arry[left]=arry[right];
arry[right]=temp;
return callme(arry, left++, right--);
}
else{
if(arry[right]%2!=0){//if right side is on odd #, then decrease index
return callme(arry, left, right--);
}
if(arry[left]%2==0){//if left side is on even #, then increase index
return callme(arry, left++, right);
}
}
return arry;
}
public static void main(String[] args){
//int index=0;
int[] arry={3,5,6,8};
int[] newarry=callme(arry, 0, arry.length-1);
System.out.print("The new sorted array is: ");
for(int i=0; i<newarry.length;i++){
System.out.print(newarry[i]+" ");
}
}
}
left++ is not the same as left + 1. If you want to call the method recursively with a left argument that is one higher, then call it with left + 1.
In this statement:
return callme(arry, left++, right--);
the way it works is this: The program saves the current value of left, adds 1 to left, but then uses the value saved before it was incremented as the argument to the recursive call. The right-- argument works the same way. So when callme calls itself, it's calling itself with the exact same arguments it was called with. So you never get to the base case.
(Something else you should know about recursion: Each time a recursive method calls itself, it will have its own copy of the local variables, including the parameters. So even though the first method increases left, that has no impact on what left will be when it's called recursively, because the recursive methods have their own left.)
If you just want the even numbers to be on the top, no need to do left and right.
You could do:
int temp;
for (int i = 0; i < array.length; i++)
if (array[i] % 2)
for (int j = i + 1; j < array.length; j++)
if !(array[j] % 2) {
temp = array[j];
array[j] = array[i];
array[i] = temp;
j = array.length;
}

Converting an Iterative Method to a Recursive one (Java)

For my discrete structures class at uni, I need to write a method that solves the formulas below:
 
s[0] = 1
s[n-1] = s[n-2] + n for all n >= 2
Unfortunately, I've not implemented many recursive methods before, so I don't really know what I'm doing. Things just aren't "clicking" for me like they normally do.
I'd appreciate help in any way possible, but I'd rather fully understand this, rather than just copypaste someone else's work.
A basic example for what this method should accomplish if n = 8...
1 + 2 = 3,
3 + 3 = 6,
6 + 4 = 10,
10 + 5 = 15,
15 + 6 = 21,
21 + 7 = 28,
28 + 8 = 36, our answer.
I've written a method to solve this NON-recursively (shown below), so I do understand the math behind it.
public static int sequenceNonRecursive(int n){
int[] s = new int[n];
s[0] = 1;
if(n >= 2){
for(int i = 1; i < n; i++){
s[i] = s[i-1] + i + 1;
}
}
return s[n-1];
}
EDIT: I solved it. Thanks for your help, everyone! Look below for my answer.
The recurrence is defined a little oddly. I would rewrite it:
S0 = 1
Si = Si-1 + i + 1 — ∀ i > 0
The routine can be simplified to not use an array:
public static int sequenceNonRecursive (int n) {
int S_0 = 1; // 0th term is 1
int S_i = S_0; // S_i starts at S_0
for(int i = 1; i <= n; i++) {
int S_i_minus_1 = S_i; // use previous result to calculate next
S_i = S_i_minus_1 + i + 1; // next is previous added with index plus 1
}
return S_i;
}
Any loop can be converted into an equivalent recursive routine. The trick is that local variables turn into function parameters for the recursive routine and the loop control turns into an if. If the condition is false, the function returns with the result. Otherwise, the function does the computation as if it is the loop body, and then uses recursion to iterate.
As an illustration, given the function:
public static int someFunction (int n) {
int result = DEFAULT_RESULT;
for (int i = 0; i < n; ++i) {
result = UPDATE_RESULT(i, n, result);
}
return result;
}
Then, the body of this function can be changed to call a recursive function instead:
public static int someFunction (int n) {
return someFunctionWithRecursion(n, 0, DEFAULT_RESULT);
}
Notice how the initial values of local variables have been converted into parameters to the recursive routine. So, the recursive routine itself may look like:
public static int someFunctionWithRecursion (int n, int i, int result) {
if (! (i < n)) {
return result;
}
result = UPDATE_RESULT(i, n, result);
return someFunctionWithRecursion(n, i+1, result);
}
Notice that in the recursive call, the result has been updated, and the control variable i has been incremented, just as an iteration would have done in the original for() loop version of the code.
As an aside: The recurrence you are working on actually has a closed form:
Sn = (½)(n+1)(n+2)
It's actually easier. Imagine that your method works for all n's and that unless n is zero (the base case) you use
sequenceRecursive(n-1)
to get the value of the previous number and just expect it to work. (and it will)
Under the hood it will recurse down to the base case and build up the value as the calls return.
Recursion is like breaking down the original problem into sub problems and trying to solve them. To start with you need to figure out the base case(which in your case is n=0). Now you can move ahead and see how you can handle cases where n > 0 by breaking it down to the base case. Creating the sequence for n then n-1 then n-2 and so on till you reach the base case is the key to solve this problem recursively.
Structure your code something like this (just giving hints, leaving you to figure out the rest of the problem):
public static int sequenceRecursive(int n){
if( n == 0 )
//return something....
else
//return something else, which recursively relies on previous values of sequenceRecursive()
}
Let's first add 1 to all n's in your second equation: (if we increase them, we need to decrease the range, seeing that it's correct should be trivial)
s[0] = 1
s[n] = s[n-1] + (n+1) for all n >= 1
Why do we want to do this?
In short, the function definition is sequence(int n), not sequence(int n-1).
Here s[i] just corresponds to calling your function with input parameter i.
And the basic idea for the code:
public static int sequence(int n){
if (/* base case */)
// return value for base case
else
// return other case, includes calling sequence(x) for some x
}
Hope that gives you enough to work from.
I got it, guys. Thank ALL of you for your help! I can't believe how stupidly simple this was. As soon as I figured it out, I gave myself a forceful facepalm. I'm pretty sure I understand recursion now.
public static int sequenceRecursive(int n){
if( n == 0 )
return 0;
else
return n + sequenceRecursive(n-1);
}

Partitioning an array on a Pivot

I am trying to write a simple algorithm for moving the elements around pivot such that the elements on the left of pivot is smaller than the pivot and the element on the right of pivot is greater than it (the same step in quick sort). I have written code that works, but after that I changed the algorithm to the below, and it is not working.
The idea of the algorithm is simple.
Have two pointers, one at the beginning of the array and one at the end of array. If the elements pointed by i are lesser than pivot, keep skipping it until we find a greater element; and keep decrementing j until we find an element greater than the smaller element. [It is a common algorithm]
Now the code
private static void sortByPivot(int[] a)
{
Random r = new Random();
int index = r.nextInt(a.length);
int pivot = a[index];
System.out.println("pivot = " + pivot);
int i =0 , j = a.length -1;
while(true)
{
while(a[i] <= pivot) i++;
while( j >0 && a[j] >= pivot) j--;
if(i <= j)
{
break;
}
else{
swap(a,i,j);
}
}
swap(a,i,index); //swap the pivot and the i
}
Swap routine :
private static void swap(int[] a, int i , int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
When I run this with the following array
int[] a = {46,3,8,4,2,6,244,76}
and when the pivot is picked as 4
the output is
4 3 8 46 2 6 244 76
For some other pivots that are in the edge, I get a null pointer exception.
Is there any flaw in the implementation. The logic seems right to me. I have been trying it for quite sometime but I am unable to fix it.
Check this implementation. It works exactly on the same principle. Try to compare and see where you are going wrong.
Note that you are supposed to swap the values of a[i] and a[j] if i <= j and also break from the loop. You are doing it on the else, which is wrong, because if a[i] is greater than the pivot and a[j] is less than the pivot by the time you reach the if, then they should be swapped if i <= j.
If you're just trying to sort it all, (I know you said "partition" but would it be a problem if the whole thing was sorted?) there are built in methods for that
java.util.Arrays.sort(int[] a)
java.util.Arrays.sort(int[] a, int fromIndex, int toIndex)
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Arrays.html
If you're requirement is to do it yourself (homework!) then try the debugging approach above; write on paper what you expect, then step through completely to see what happens
The logic is not correct. You have just written the code. Just take a moment and dry run this program on any input and you will directly find the flaw.
A better approach would be to take the approach depicted here on wikipedia
This is the inplace version of partitioning an array used in quick sort. Hope it solves your problem.
For anyone that's coming here years later I think the issue is that this conditional should be >= .
if(i <= j)
{
break;
}
Looks like the code is breaking the loop in the first iteration.
All that's running is the last swap function.

Categories