Project Euler #3: Largest prime factor - algorithm

Optimizing code for finding the largest prime factor for a given number?
Below code worked for small input case but didn't work for large input case
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long i=n;
if(n%2==0)
i=i-1;
for(;i>=1;i-=2)
{
if(n%i==0&&prime(i))
break;
}
if(n%2==0&&i<2)
System.out.println(2);
else
System.out.println(i);
}
public static boolean prime(long n)
{
if(n%2==0)
return false;
for(long i=3;i<=Math.sqrt(n);i+=2)
{
if(n%i==0)
return false;
}
return true;
}

Try this
public long largestPrime(long n){
long ans = 0;
while(n % 2 == 0){
n/=2;
ans = Math.max(ans, 2);
}
for(long i = 3; i*i <= n; i++){
while(n%i == 0){
n /= i;
ans = Math.max(ans, i);
}
}
if(n > 1) ans = Math.max(n, ans);
return ans;
}

I've written the code below and it works for big numbers very fast.
public static void main(String[] args) {
long result = largestPrimeFactor(600851475143L);
System.out.println("Result : " + result);
}
public static long largestPrimeFactor(long num) {
long largest = -1;
long i = 2;
while (num > 1) {
if (num % i == 0) {
num /= i;
if (largest < i)
largest = i;
} else {
i++;
}
}
return largest;
}

Related

How to efficiently compute weird numbers

I am trying to print n weird numbers where n is really big number (eg: 10000).
I found this site to check the algorithm for n 600 if I have some errors:
http://www.numbersaplenty.com/set/weird_number/more.php
However, my algorithm is really slow in bigger numbers:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
int n = 2;
for ( int count = 1 ; count <= 15000 ; n += 2 ) {
if (n % 6 == 0) {
continue;
}
List<Integer> properDivisors = getProperDivisors(n);
int divisorSum = properDivisors.stream().mapToInt(i -> i.intValue()).sum();
if ( isDeficient(divisorSum, n) ) {
continue;
}
if ( isWeird(n, properDivisors, divisorSum) ) {
System.out.printf("w(%d) = %d%n", count, n);
count++;
}
}
}
private static boolean isWeird(int n, List<Integer> divisors, int divisorSum) {
return isAbundant(divisorSum, n) && ! isSemiPerfect(divisors, n);
}
private static boolean isDeficient(int divisorSum, int n) {
return divisorSum < n;
}
private static boolean isAbundant(int divisorSum, int n) {
return divisorSum > n;
}
private static boolean isSemiPerfect(List<Integer> divisors, int sum) {
int size = divisors.size();
// The value of subset[i][j] will be true if there is a subset of divisors[0..j-1] with sum equal to i
boolean subset[][] = new boolean[sum+1][size+1];
// If sum is 0, then answer is true
for (int i = 0; i <= size; i++) {
subset[0][i] = true;
}
// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++) {
subset[i][0] = false;
}
// Fill the subset table in bottom up manner
for ( int i = 1 ; i <= sum ; i++ ) {
for ( int j = 1 ; j <= size ; j++ ) {
subset[i][j] = subset[i][j-1];
int test = divisors.get(j-1);
if ( i >= test ) {
subset[i][j] = subset[i][j] || subset[i - test][j-1];
}
}
}
return subset[sum][size];
}
private static final List<Integer> getProperDivisors(int number) {
List<Integer> divisors = new ArrayList<Integer>();
long sqrt = (long) Math.sqrt(number);
for ( int i = 1 ; i <= sqrt ; i++ ) {
if ( number % i == 0 ) {
divisors.add(i);
int div = number / i;
if ( div != i && div != number ) {
divisors.add(div);
}
}
}
return divisors;
}
}
I have three easy breakouts:
If a number is divisable by 6 it is semiperfect which means it cannot be weird
If a number is deficient this means it cannot be weird
The above points are based on https://mathworld.wolfram.com/DeficientNumber.html
If a a number is odd it cannot be weird at least for 10^21 numbers (which is good for the numbers I am trying to obtain).
The other optimization that I used is the optimization for finding all the dividers of a number. Instead of looping to n, we loop to SQRT(n).
However, I still need to optimize:
1. isSemiPerfect because it is really slow
2. If I can optimize further getProperDivisors it will be good too.
Any suggestions are welcome, since I cannot find any more optimizations to find 10000 weird numbers in reasonable time.
PS: Any code in Java, C#, PHP and JavaScript are OK for me.
EDIT: I found this topic and modified isSemiPerfect to look like this. However, it looks like it does not optimize but slow down the calculations:
private static boolean isSemiPerfect(List<Integer> divisors, int n) {
BigInteger combinations = BigInteger.valueOf(2).pow(divisors.size());
for (BigInteger i = BigInteger.ZERO; i.compareTo(combinations) < 0; i = i.add(BigInteger.ONE)) {
int sum = 0;
for (int j = 0; j < i.bitLength(); j++) {
sum += i.testBit(j) ? divisors.get(j) : 0;
}
if (sum == n) {
return true;
}
}
return false;
}
The issue is indeed in function isSemiPerfect. I transposed your code in C++, it was still quite slow.
Then I modified this function by using backtracking. I now obtain the first 15000 weird values in about 15s. My interpretation is that in about all the cases, the value is semiperfect, and the backtracking function converges rapidly.
Note also that in my backtracking implementation, I sort the divisors, which allow to reduce the number of cases to be examined.
Edit 1: an error was corrected in getProperDivisors. Final results did not seem to be modified !
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <algorithm>
// return true if sum is obtained
bool test_sum (std::vector<int>& arr, int amount) {
int n = arr.size();
std::sort(arr.begin(), arr.end(), std::greater<int>());
std::vector<int> bound (n);
std::vector<int> select (n);
bound[n-1] = arr[n-1];
for (int i = n-2; i >= 0; --i) {
bound[i] = bound[i+1] + arr[i];
}
int sum = 0; // current sum
int i = 0; // index of the coin being examined
bool up_down = true;
while (true) {
if (up_down) {
if (i == n || sum + bound[i] < amount) {
up_down = false;
i--;
continue;
}
sum += arr[i];
select[i] = 1;
if (sum == amount) return true;
if (sum < amount) {
i++;
continue;
}
up_down = false;
if (select[i] == 0) i--;
} else { // DOWN
if (i < 0) break;
if (select[i] == 0) {
i--;
} else {
sum -= arr[i];
select[i] = 0;
i++;
up_down = true;
}
}
}
return false;
}
bool isDeficient(int divisorSum, int n) {
return divisorSum < n;
}
bool isAbundant(int divisorSum, int n) {
return divisorSum > n;
}
bool isSemiPerfect(std::vector<int> &divisors, int sum) {
int size = divisors.size();
// The value of subset[i][j] will be true if there is a subset of divisors[0..j-1] with sum equal to i
//bool subset[sum+1][size+1];
std::vector<std::vector<bool>> subset(sum+1, std::vector<bool> (size+1));
// If sum is 0, then answer is true
for (int i = 0; i <= size; i++) {
subset[0][i] = true;
}
// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++) {
subset[i][0] = false;
}
// Fill the subset table in bottom up manner
for ( int i = 1 ; i <= sum ; i++ ) {
for ( int j = 1 ; j <= size ; j++ ) {
subset[i][j] = subset[i][j-1];
int test = divisors[j-1];
if ( i >= test ) {
subset[i][j] = subset[i][j] || subset[i - test][j-1];
}
}
}
return subset[sum][size];
}
bool isWeird(int n, std::vector<int> &divisors, int divisorSum) {
//return isAbundant(divisorSum, n) && !isSemiPerfect(divisors, n);
return isAbundant(divisorSum, n) && !test_sum(divisors, n);
}
std::vector<int> getProperDivisors_old(int number) {
std::vector<int> divisors;
long sqrtn = sqrt(number);
for ( int i = 1 ; i <= sqrtn ; i++ ) {
if ( number % i == 0 ) {
divisors.push_back(i);
int div = number / i;
if (div != i && div != number) {
divisors.push_back(div);
}
}
}
return divisors;
}
std::vector<int> getProperDivisors(int number) {
std::vector<int> divisors;
long sqrtn = sqrt(number);
divisors.push_back(1);
for ( int i = 2 ; i <= sqrtn ; i++ ) {
if (number % i == 0) {
divisors.push_back(i);
int div = number/i;
if (div != i) divisors.push_back(div);
}
}
return divisors;
}
int main() {
int n = 2, count;
std::vector<int> weird;
int Nweird = 15000;
for (count = 0; count < Nweird; n += 2) {
if (n % 6 == 0) continue;
auto properDivisors = getProperDivisors(n);
int divisorSum = std::accumulate (properDivisors.begin(), properDivisors.end(), 0);
if (isDeficient(divisorSum, n) ) {
continue;
}
if (isWeird(n, properDivisors, divisorSum)) {
//std::cout << count << " " << n << "\n";
weird.push_back (n);
count++;
}
}
for (int i = Nweird - 10; i < Nweird; ++i) {
std::cout << weird.at(i) << " ";
}
std::cout << "\n";
}
EDIT 2 The generation of Divisors were completely redefined. It uses now prime decomposition. Much more complex, but global time divided by 7.5. Generation of weird numbers take now 2s on my PC.
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <algorithm>
template <typename T>
struct factor {T val = 0; T mult = 0;};
template <typename T>
class decompo {
private:
std::vector<T> memory = {2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 39, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
T index = 0;
public:
decompo () {};
void reset () {index = 0;};
T pop () {index = memory.size() - 1; return memory[index];};
T get_next ();
std::vector<T> find_all_primes (T n);
std::vector<factor<T>> decomp (T n);
std::vector<T> GetDivisors (T n);
void complete (T n);
};
template <typename T>
T decompo<T>::get_next () {
++index;
if (index <= memory.size()) {
return memory[index-1];
}
T n = memory.size();
T candidate = memory[n-1] + 2;
while (1) {
bool found = true;
for (T i = 1; memory[i] * memory[i] <= candidate; ++i) {
if (candidate % memory[i] == 0) {
found = false;
break;
}
}
if (found) {
memory.push_back (candidate);
return candidate;
}
candidate += 2;
}
}
template <typename T>
std::vector<T> decompo<T>::find_all_primes (T n) {
reset();
std::vector<T> result;
while (1) {
T candidate = get_next();
if (candidate <= n) {
result.push_back (candidate);
} else {
return result;
}
}
}
template <typename T>
void decompo<T>::complete (T n) {
T last = pop();
while (last < n) {
last = get_next();
}
return;
}
template <typename T>
std::vector<factor<T>> decompo<T>::decomp (T n) {
reset();
std::vector<factor<T>> result;
if (n < 2) return result;
T candidate = get_next();
T last_prime = 0;
while (candidate*candidate <= n) {
if (n % candidate == 0) {
if (candidate == last_prime) {
result[result.size()-1].mult ++;
} else {
result.push_back ({candidate, 1});
last_prime = candidate;
}
n /= candidate;
} else {
candidate = get_next();
}
}
if (n > 1) {
if (n != last_prime) result.push_back ({n, 1});
else result[result.size()-1].mult ++;
}
return result;
}
template <typename T>
std::vector<T> decompo<T>::GetDivisors (T n) {
std::vector<T> div;
auto primes = decomp (n);
int n_primes = primes.size();
std::vector<int> exponent (n_primes, 0);
div.push_back(1);
int current_index = 0;
int product = 1;
std::vector<int> product_partial(n_primes, 1);;
while (true) {
current_index = 0;
while (current_index < n_primes && exponent[current_index] == primes[current_index].mult) current_index++;
if (current_index == n_primes) break;
for (int index = 0; index < current_index; ++index) {
exponent[index] = 0;
product /= product_partial[index];
product_partial[index] = 1;
}
exponent[current_index]++;
product *= primes[current_index].val;
product_partial[current_index] *= primes[current_index].val;
if (product != n && product != 1) div.push_back (product);
}
return div;
}
// return true if sum is obtained
bool test_sum (std::vector<int>& arr, int amount) {
int n = arr.size();
std::sort(arr.begin(), arr.end(), std::greater<int>());
std::vector<int> bound (n);
std::vector<int> select (n);
bound[n-1] = arr[n-1];
for (int i = n-2; i >= 0; --i) {
bound[i] = bound[i+1] + arr[i];
}
int sum = 0; // current sum
int i = 0; // index of the coin being examined
bool up_down = true;
while (true) {
if (up_down) {
if (i == n || sum + bound[i] < amount) {
up_down = false;
i--;
continue;
}
sum += arr[i];
select[i] = 1;
if (sum == amount) return true;
if (sum < amount) {
i++;
continue;
}
up_down = false;
if (select[i] == 0) i--;
} else { // DOWN
if (i < 0) break;
if (select[i] == 0) {
i--;
} else {
sum -= arr[i];
select[i] = 0;
i++;
up_down = true;
}
}
}
return false;
}
bool isDeficient(int divisorSum, int n) {
return divisorSum < n;
}
bool isAbundant(int divisorSum, int n) {
return divisorSum > n;
}
bool isSemiPerfect(std::vector<int> &divisors, int sum) {
int size = divisors.size();
// The value of subset[i][j] will be true if there is a subset of divisors[0..j-1] with sum equal to i
//bool subset[sum+1][size+1];
std::vector<std::vector<bool>> subset(sum+1, std::vector<bool> (size+1));
// If sum is 0, then answer is true
for (int i = 0; i <= size; i++) {
subset[0][i] = true;
}
// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++) {
subset[i][0] = false;
}
// Fill the subset table in bottom up manner
for ( int i = 1 ; i <= sum ; i++ ) {
for ( int j = 1 ; j <= size ; j++ ) {
subset[i][j] = subset[i][j-1];
int test = divisors[j-1];
if ( i >= test ) {
subset[i][j] = subset[i][j] || subset[i - test][j-1];
}
}
}
return subset[sum][size];
}
bool isWeird(int n, std::vector<int> &divisors, int divisorSum) {
//return isAbundant(divisorSum, n) && !isSemiPerfect(divisors, n);
return isAbundant(divisorSum, n) && !test_sum(divisors, n);
}
std::vector<int> getProperDivisors(int number) {
std::vector<int> divisors;
long sqrtn = sqrt(number);
divisors.push_back(1);
for ( int i = 2 ; i <= sqrtn ; i++ ) {
if (number % i == 0) {
divisors.push_back(i);
int div = number/i;
if (div != i) divisors.push_back(div);
}
}
return divisors;
}
int main() {
decompo <int> decomposition;
decomposition.complete (1e3); // not relly useful
int n = 2, count;
std::vector<int> weird;
int Nweird = 15000;
for (count = 0; count < Nweird; n += 2) {
if (n % 6 == 0) continue;
//auto properDivisors = getProperDivisors(n);
auto properDivisors = decomposition.GetDivisors(n);
int divisorSum = std::accumulate (properDivisors.begin(), properDivisors.end(), 0);
if (isDeficient(divisorSum, n) ) {
continue;
}
if (isWeird(n, properDivisors, divisorSum)) {
//std::cout << count << " " << n << "\n";
weird.push_back (n);
count++;
}
}
for (int i = Nweird - 10; i < Nweird; ++i) {
std::cout << weird.at(i) << " ";
}
std::cout << "\n";
}

Binary Search Symbol Table implementation going inside infinite loop

I am trying to implement 'Binary Search in an ordered array' from the book 'Algorithms (fourth edition) by Robert Sedgewick & Kevin Wayne' (on page 381). However my code is going inside infinite loop. Please help. Below is the code:
public class BinarySearchST<Key extends Comparable<Key>, Value>{
private Key keys[];
private Value values[];
private int N;
public BinarySearchST(int capacity){
keys = (Key[]) new Comparable[capacity];
values = (Value[]) new Object[capacity];
}
public int size(){
return N;
}
public boolean isEmpty(){
return N == 0;
}
public int rank(Key key){
int lo = 0, hi = N-1;
while(lo <= hi){
int mid = (lo + (hi - lo))/2;
int comp = key.compareTo(keys[mid]);
if(comp < 0) hi = mid - 1;
else if(comp > 0) lo = mid + 1;
else return mid;
}
return lo;
}
public Value get(Key key){
if(isEmpty()) return null;
int rank = rank(key);
if(rank < N && key.compareTo(keys[rank]) == 0)
return values[rank];
else
return null;
}
public void put(Key key, Value value){
int rank = rank(key);
if(rank < N && key.compareTo(keys[rank]) == 0){//key already existing, just update value.
values[rank] = value;
return;
}
for(int i = N; i > rank; i--){
keys[i] = keys[i-1]; values[i] = values[i-1];
}
keys[rank] = key;
values[rank] = value;
N++;
}
public static void main(String[] args){
BinarySearchST<String, Integer> st = new BinarySearchST<String, Integer>(10);
st.put("A", 10);
st.put("B", 100);
st.put("C", 1000);
StdOut.println(st.get("A"));
}
}
This appears to be correct to me, but looks like some issue inside put() for loop.
use int mid = (lo + hi)/2.
You are using int mid = (lo+(hi-lo))/2 which reduces to hi/2. So, eventually your middle will be less than your lo and will not converge causing infinite loop.

print shapes in java

I want to print this shape big X from collection of small x using recursion
this is my code
private static void shape(PrintWriter output, int times, int k, int times2) {
if(times < 0){
return;
} else{
for (int i =0; i<times; i++){
if (i==times)
output.print("X");
else if(i==k)
output.print("X");
else
output.print(" ");
}
output.println();
shape(output,times-1,k+1,times2);
}
}
but I couldn't print the shape requested
Try this.
static void shape(PrintWriter output, int size, int index) {
if (index >= size)
return;
char[] buffer = new char[size];
Arrays.fill(buffer, ' ');
buffer[index] = buffer[size - index - 1] = 'X';
output.println(new String(buffer));
shape(output, size, index + 1);
}
and
try (PrintWriter output = new PrintWriter(new OutputStreamWriter(System.out))) {
shape(output, 11, 0);
}
Just change
int arr[] = new int[times]
to
int arr[] = new int[times2]
where times2 is the width of a single row.
However a more cleaner way would be:
public class InputTest {
private static void FCITshape(int times, int k,int times2) {
if (times < 0) {
return;
} else {
for (int i = 0; i <= times2; i++) {
if (i == times)
System.out.print("X");
else if (i == k)
System.out.print("X");
else
System.out.print(" ");
}
System.out.println();
FCITshape(times - 1, k + 1, times2);
}
}
public static void main(String[] args) {
FCITshape(10, 0, 10);
}
}
Regards.
With recursion
Now just call printX(0, 10);
public static void printX(int x, int l) {
if (x <= l) {
if (x < l / 2) {
for (int i = 0; i < x ; i++) {
System.out.print(" ");
}
} else {
for (int i = 0; i < l - x; i++) {
System.out.print(" ");
}
}
System.out.print("x");
if (x < l / 2) {
for (int j = 0; j < l - x * 2 - 1; j++) {
System.out.print(" ");
}
} else {
for (int j = 0; j < (x * 2 - l) - 1; j++) {
System.out.print(" ");
}
}
if (x != l / 2) {
System.out.print("x");
}
System.out.println();
printX(x + 1, l);
}
}

Optimizing quick sort

I am implementing quick sort algorithm in java and here is the code :
public class quickSort {
private int array[];
private int length;
public void sort(int[] inputArr) {
if (inputArr == null || inputArr.length == 0) {
return;
}
this.array = inputArr;
length = inputArr.length;
quickSorter(0, length - 1);
}
private void quickSorter(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
// calculate pivot number, I am taking pivot as middle index number
int pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];
// Divide into two arrays
while (i <= j) {
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
exchangeNumbers(i, j);
//move index to next position on both sides
i++;
j--;
}
}
// call quickSort() method recursively
if (lowerIndex < j)
quickSorter(lowerIndex, j);
if (i < higherIndex)
quickSorter(i, higherIndex);
}
private void exchangeNumbers(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Then I implement it with (median of three)
public class quickSort {
private int array[];
private int length;
public void sort(int[] inputArr) {
if (inputArr == null || inputArr.length == 0) {
return;
}
this.array = inputArr;
length = inputArr.length;
quickSorter(0, length - 1);
}
private void quickSorter(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
int mid = lowerIndex+(higherIndex-lowerIndex)/2;
if (array[i]>array[mid]){
exchangeNumbers( i, mid);
}
if (array[i]>array[j]){
exchangeNumbers( i, j);
}
if (array[j]<array[mid]){
exchangeNumbers( j, mid);
}
int pivot = array[mid];
// Divide into two arrays
while (i <= j) {
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
exchangeNumbers(i, j);
//move index to next position on both sides
i++;
j--;
}
}
// call quickSort() method recursively
if (lowerIndex < j)
quickSorter(lowerIndex, j);
if (i < higherIndex)
quickSorter(i, higherIndex);
}
private void exchangeNumbers(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
and the testing main :
public static void main(String[] args) {
File number = new File ("f.txt");
final int size = 10000000;
try{
quickSortOptimize opti = new quickSortOptimize();
quickSort s = new quickSort();
PrintWriter printWriter = new PrintWriter(number);
for (int i=0;i<size;i++){
printWriter.println((int)(Math.random()*100000));
}
printWriter.close();
Scanner in = new Scanner (number);
int [] arr1 = new int [size];
for (int i=0;i<size;i++){
arr1[i]=Integer.parseInt(in.nextLine());
}
long a=System.currentTimeMillis();
opti.sort(arr1);
long b=System.currentTimeMillis();
System.out.println("Optimaized quicksort: "+(double)(b-a)/1000);
in.close();
int [] arr2 = new int [size];
Scanner in2= new Scanner(number);
for (int i=0;i<size;i++){
arr2[i]=Integer.parseInt(in2.nextLine());
}
long c=System.currentTimeMillis();
s.sort(arr2);
long d=System.currentTimeMillis();
System.out.println("normal Quicksort: "+(double)(d-c)/1000);
}catch (Exception ex){ex.printStackTrace();}
}
The problem is that this method of optimization should improve performance by 5%
but, what happens actually is that I have done this test many times and almost always getting better result on normal quicksort that optimized one
so what is wrong with the second implementation
A median of three (or more) will usually be slower for input that's randomly ordered.
A median of three is intended to help prevent a really bad case from being quite as horrible. There are ways of making it pretty bad anyway, but at least avoids the problem for a few common orderings--e.g., selecting the first element as the pivot can produce terrible results if/when (most of) the input is already ordered.

MergeSort gives StackOverflow error

this is the code for the mergeSort,this gives an stackoverflow error in line 53 and 54(mergeSort(l,m); and mergeSort(m,h);)
Any help will be regarded so valuable,please help me out,i am clueless,Thank you.
package codejam;
public class vector {
static int[] a;
static int[] b;
public static void main(String[] args) {
int[] a1 = {12,33,2,1};
int[] b1 = {12,333,11,1};
mergeSort(0,a1.length);
a1=b1;
mergeSort(0,b1.length);
for (int i = 0; i < a1.length; i++) {
System.out.println(a[i]);
}
}
public static void merge(int l,int m,int h) {
int n1=m-l+1;
int n2 = h-m+1;
int[] left = new int[n1];
int[] right = new int[n2];
int k=l;
for (int i = 0; i < n1 ; i++) {
left[i] = a[k];
k++;
}
for (int i = 0; i < n2; i++) {
right[i] = a[k];
k++;
}
left[n1] = 100000000;
right[n1] = 10000000;
int i=0,j=0;
for ( k =l ; k < h; k++) {
if(left[i]>=right[j])
{
a[k] = right[j];
j++;
}
else
{
a[k] = left[i];
i++;
}
}
}
public static void mergeSort(int l,int h) {
int m =(l+h)/2;
if(l<h)
{
mergeSort(l,m);
mergeSort(m,h);
merge(l,m,h);;
}
}
}
Following is the recursive iterations table of the mergeSort function with argument l=0 and h=4
when the value of l is 0 and value of h is 1 , expression calculate m value which turn out to be 0 but we are checking condition with h which is still 1 so 0<1 become true , recursive calls of this mergeSort function forms a pattern , this pattern doesn't let the function to terminate , stack runs out of memory , cause stackoverflow error.
import java.lang.*;
import java.util.Random;
public class MergeSort {
public static int[] merge_sort(int[] arr, int low, int high ) {
if (low < high) {
int middle = low + (high-low)/2;
merge_sort(arr,low, middle);
merge_sort(arr,middle+1, high);
arr = merge (arr,low,middle, high);
}
return arr;
}
public static int[] merge(int[] arr, int low, int middle, int high) {
int[] helper = new int[arr.length];
for (int i = 0; i <=high; i++){
helper[i] = arr[i];
}
int i = low;
int j = middle+1;
int k = low;
while ( i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
arr[k++] = helper[i++];
} else {
arr[k++] = helper[j++];
}
}
while ( i <= middle){
arr[k++] = helper[i++];
}
while ( j <= high){
arr[k++] = helper[j++];
}
return arr;
}
public static void printArray(int[] B) {
for (int i = 0; i < B.length ; i++) {
System.out.print(B[i] + " ");
}
System.out.println("");
}
public static int[] populateA(int[] B) {
for (int i = 0; i < B.length; i++) {
Random rand = new Random();
B[i] = rand.nextInt(20);
}
return B;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int A[] = new int[10];
A = populateA(A);
System.out.println("Before sorting");
printArray(A);
A = merge_sort(A,0, A.length -1);
System.out.println("Sorted Array");
printArray(A);
}
}

Resources