Calculating the factorial of every element in an integer array - java

I need to create a Method that has 2 parameters in Java, upperborder and lowerborder. This method must create an array from the number 2 to the number 10.
Then I must implement another method, that calculates the factorial for a given number.
Then I must implement a third method that calculates the factorial for every element in the created array and test all these methods in a TestClass.
I know how to do this, but apparently I'm making some kind of a mistake in my code and it gives me the StackOverflow exception. I read the code a couple of times, but I can't seem to quite understand where I'm wrong.
package fakultaetinarray;
public final class FakultaetinArray{
private int i;
private int[] a;
private int j;
public FakultaetinArray(){
System.out.println("Given array : ");
createArray(1, 9);
System.out.println("Factorial for every element : ");
FakinArray();
}
public int fakRe(int n){
if(n == 1){
return n;
}
return n * fakRe(n - 1);
}
public void createArray(int untergrenze, int obergrenze){
this.a = new int[obergrenze];
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
}
public void FakinArray(){
a[0] = 2;
for(i = 1; i < a.length; i++){
int fak = fakRe(a[i]);
a[i] = fak;
System.out.println(fak);
}
}
}

The reason you're getting StackOverflowErrors is due to your recursive method not having a case when n == 0.
The reason that your values are coming in as 0 is due to how you're constructing your loop.
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
It's unclear why you're using j here at all, and i is initialized to its default value of 0, so in all reality, you're only ever filling one element of your array with a positive value and all of the others are at zero.
You need to reconsider how your loops are constructed. I would strongly encourage you not to make them fields, but declare them as part of the loop construct instead.

if(n == 1){ is not a strong enough condition to block the recursion: n can go below 1. In your particular case, you have a situation where n is 0.
Consider unwinding the recursion to a simple loop in any case. As a rule of thumb, recursion is not good for O(N) stuff.

Related

Counting Sort issue

public static void countingSort(Integer[] a, int n) {
//TODO
//COMPLETE THIS METHOD
int[] counter = new int[n+1];
int[] sorted = new int[a.length];
Arrays.fill(counter,0);
// fills counter array with each number count
for ( int i = 0 ; i < a.length; i++){
counter[a[i]] += 1;
} // adds n-1 index + n index
for (int i = 1; i < counter.length; i++) {
counter[i] = (counter[i] + counter[i-1]);
} // shifts array to the right
for (int i = counter.length-1; i > 0; i--) {
counter[i] = counter[i-1];
} // fills sorted array with the sorted out counts
for (int i = 0; i < a.length; i++ ){
sorted[counter[a[i]]] = a[i];
counter[a[i]]++;
}
}
When ran it throws an array out of bound exception in the body of the first for loop. Im having trouble seeing it, if anyone could help guide me, it'd be much appreciated.
When ran it throws an array out of bound exception in the body of the
first for loop.
That would be this:
for ( int i = 0 ; i < a.length; i++){
counter[a[i]] += 1;
}
Im having trouble seeing it, if anyone could help
guide me, it'd be much appreciated.
An ArrayIndexOutOfBoundsException in that loop can only mean that you are exceeding the bounds of a or those of counter. It is clear from inspection that you are not exceeding the bounds of a (though you could both eliminate that possibility and make the code a bit cleaner by switching to an enhanced for loop). The only remaining possibility is that you are exceeding the bounds of counter.
The approach you've implemented supports only non-negative integers in the input array, and requires the method invoker to pass an upper bound on the element values as the second parameter. If those constraints are not satisfied then an exception such as you observe will be thrown.
That is, if the exception is thrown where you say it is, then the problem is with the input.

Program entering in a infinite loop only with a specific value

I just started with java and while was doing an exercise about permutations (the exercise asked to create a permutation of N elements using an array a[] meeting the requirement that no a[i] is equal to i.) I've created the following code. While testing it, I realized that it entered in a infinite loop sometimes when N = 6 specifically.
Any thoughts on where is the problem?
public class GoodPerm {
public static void main(String arg[]) {
int n = Integer.parseInt(arg[0]);
int[] guests = new int[n];
for (int i = 0; i < n; i++) {
guests[i] = i;
}
for (int i = 0; i < n; i++) {
int r = i + (int) (Math.random() * (n - i));
int q = guests[r];
guests[r] = guests[i];
guests[i] = q;
if(guests[i] == i){
i --;
}
}
for(int q : guests){
System.out.println(q);
}
}
}
Maybe the code enters in a inf-loop in another values, but I didn't found any others.
This code can always enter an inf-loop. As I understand the code, you try to do some random switches to achieve your needed result. But if the last element of your array has never been switched, it won't be possible to switch it to any "later/higher" position (because there are no more). In the "last" iteration of your second for-loop (so i + 1 == n holds at the beginning) r will always evaluate to i thus no real switch happens. If the last element is still in place, you gonna repeat this forever.

Making 2 Modifications to a Bubblesort Program

I have to make the following 2 modifications to a simple bubblesort program:
After the first pass, the largest number is guaranteed to be in the highest-numbered element of the array; after the second pass, the two highest numbers are “in place”; and so on. Instead of making nine comparisons on every pass, modify the bubble sort to make eight comparisons on the second pass, seven on the third, and so on.
The data in the array may already be in the proper order or near proper order, so why make nine passes if fewer will suffice? Modify the sort to check at the end of each pass if any swaps have been made. If none have been made, the data must already be in the proper order, so the program should terminate. If swaps have been made, at least one more pass is needed."
Any help as to how I should approach these would be greatly appreciated!
//sort elements of array with bubble sort
public static void bubbleSort (int array2[])
{
//loop to control number of passes
for (int pass = 1; pass < array2.length; pass++)
{
//loop to control number of comparisons
for (int element = 0; element < array2.length - 1; element++)
{
//compare side-by-side elements and swap them if
//first element is greater than second element
if (array2[element] > array2[element + 1]){
swap (array2, element, element + 1);
}
}
}
}
//swap two elements of an array
public static void swap (int array3[], int first, int second)
{
//temporary holding area for swap
int hold;
hold = array3[first];
array3[first] = array3[second];
array3[second] = hold;
}
I think this will do for you. A boolean is added to check and the run (j) is subtracted from the input.length for each run.
public static int[] bubbleSort(int input[])
{
int i, j, tmp;
bool changed;
for (j = 0; j < input.length; j++)
{
changed = false;
for (i = 1; i < input.length - j; i++)
{
if (tmp[i-1] > input[i])
{
tmp= input[i];
input[i] = input[i-1];
input[i-1] = tmp;
changed = true;
}
}
if (!changed) return input;
}
return input;
}

Dynamically change the number of nested for loops

I don't know if this is a stupid question, but I need to dynamically change the number of for-loops without using recursion.
For example, if n=3, I need 3 nested for-loops.
for(int i=0; i<size; i++){
for(int j=0; j<size-1; j++){
for(int k=0; k<size-2; k++){
//do something
}
}
}
If n=5:
for(int i=0; i<size; i++){
for(int j=0; j<size-1; j++){
for(int k=0; k<size-2; k++){
for(int l=0; l<size-3; l++){
for(int m=0; m<size-4; m++){
//do something
}
}
}
}
}
Is there any way to achieve this without recursion?
Another question: what is the use of Multiple Dispatch in Java? I'm trying to code something in ONE METHOD, and it should run different events in different cases of the parameter. NO IF STATEMENTS / TERNARY OPERATORS / CASES.
NOTE: I can ONLY have one method (part of the problem), and cannot use recursion. Sorry.
Think about how many times you run through this loop. It looks like (size!) / (size - n)!:
int numLoops = 1;
for (int i = 0; i < n; i++) {
numLoops*= (size - i);
}
for (int i = 0; i < numLoops; i++) {
//do something
}
It depends what exactly you're trying to do. Recursion can always be replaced with iteration (see this post for examples using a Stack to store state).
But perhaps the modulo (%) operator could work here? i.e. Have a single loop that increments a variable (i) and then the other variables are calculated using modulo (i % 3 etc). You could use a Map to store the values of the variables indirectly, if there are a varying number of variables.
You have to create array of loop counters and increment it manually.
Quick and dirty example:
public static void nestedFors(int n, int size) {
assert n > size;
assert size > 0;
int[] i = new int[n];
int l = n - 1;
while(l >= 0) {
if(l == n - 1) {
System.out.println(Arrays.toString(i));
}
i[l]++;
if(i[l] == size - l) {
i[l] = 0;
l--;
} else if(l < n - 1) {
l++;
}
}
}
Replace System.out.println(Arrays.toString(i)) with your own code.
You can check it here: http://ideone.com/IKbDUV
It's a bit convoluted, but: here is a way to do it without recursion, in one function and without ifs.
public static void no_ifs_no_recursion(int n){
int[] helper = new int[n-1];
int[] pointers = new int[n]; //helper for printing the results
int totalsize = 1;
for (int loops = 2; loops <= n; loops++){
helper[n - loops] = totalsize;
totalsize*=loops;
}
for (int i=0; i<totalsize; i++){
int carry = i;
for (int loops = 0; loops < n-1; loops++){
pointers[loops] = carry/helper[loops];
carry = carry - (pointers[loops]*helper[loops]);
}
System.out.println(Arrays.toString(pointers));
//or do something else with `i` -> `pointers[0]`, `j` -> `pointers[1]`, `k` -> `pointers[2]` etc..
}
}
I think you need a backtracking algorithm.
But then you would replace your nested loops with recursion.
I don't want to post links here as seems moderators don't like that.
Look at "eight queens puzzle" (you can Google it), you will get my idea.
I know this idea works as I've posed this same question (which you have) to myself on many occasions, and I've applied it several times successfully.
Here is a small example (I changed it as the previous one was a bit complex).
public class Test001 {
public static void main(String[] args) {
loop(0, 5, 10);
}
/**
* max_level - the max count of nesting loops
* size - the size of the collection
*
* 0 - top most level
* level 1 - nested into 0
* level 2 - nested into 1
* ...
* and so on.
*/
private static void loop(int level, int max_level, int size){
if (level > max_level) return;
for (int i=0; i<size-level; i++){
System.out.println("Now at level: " + level + " counter = " + i);
loop(level + 1, max_level, size);
}
}
}
But this still uses recursion.

Finding the distance between the two closest elements in an array of numbers

So I'm teaching myself algorithms from this book I purchased, and I have a pseudo-code for Finding the distance between the two closetst elements in an array of numbers
MinDistance(a[0...n-1])
Input: Array A of numbers
Output: Minimum Distance between two of its elements
dMin <- maximum integer
for i=0 to n-1 do
for j=0 to n-1 do
if i!=j and | A[i] - A[j] | < dMin
dMin = | A[i]-A[j] |
return dMin
However, I wanted to make improvements to this algorithmic solution. Change what's already there, or rewrite all together. Can someone help?
I wrote the function and class in Java to test the pseudo-code? Is that correct? And once again, how can I make it better from efficiency standpoint.
//Scanner library allowing the user to input data
import java.lang.Math.*;
public class ArrayTester{
//algorithm for finding the distance between the two closest elements in an array of numbers
public int MinDistance(int [] ar){
int [] a = ar;
int aSize = a.length;
int dMin = 0;//MaxInt
for(int i=0; i< aSize; i++)
{
for(int j=i+1; j< aSize;j++)
{
dMin = Math.min(dMin, Math.abs( a[i]-a[j] );
}
}
return dMin;
}
//MAIN
public static void main(String[] args){
ArrayTester at = new ArrayTester();
int [] someArray = {9,1,2,3,16};
System.out.println("NOT-OPTIMIZED METHOD");
System.out.println("Array length = "+ someArray.length);
System.out.println("The distance between the two closest elements: " + at.MinDistance(someArray));
} //end MAIN
} //END CLASS
SO I updated the function to minimize calling the Math.abs twice. What else can I do improve it. If I was to rewrite it with sort, would it change my for loops at all, or would it be the same just theoretically run faster.
public int MinDistance(int [] ar){
int [] a = ar;
int aSize = a.length;
int dMin = 0;//MaxInt
for(int i=0; i< aSize; i++)
{
for(int j=i+1; j< aSize;j++)
{
dMin = Math.min(dMin, Math.abs( a[i]-a[j] );
}
}
return dMin;
}
One obvious efficiency improvement: sort the integers first, then you can look at adjacent ones. Any number is going to be closest to its neighbour either up or down.
That changes the complexity from O(n2) to O(n log n). Admittedly for the small value of n shown it's not going to make a significant difference, but in terms of theoretical complexity it's important.
One micro-optimization you may want to make: use a local variable to store the result of Math.abs, then you won't need to recompute it if that turns out to be less than the minimum. Alternatively, you might want to use dMin = Math.min(dMin, Math.abs(a[i] - a[j])).
Note that you need to be careful of border conditions - if you're permitting negative numbers, your subtraction might overflow.
That's a naive solution of O(n^2).
Better way:
Sort the array, then go over it once more and check the distance between the sorted items.
This will work because they are in ascending order, so the number with the nearest value is adjacent.
That solution will be O(nlogn)
First of all, before making it fast, make it correct. Why is dmin initialized with the length of the array? If the array is [1, 1000], the result of your algorithm will be 2 instead of 999.
Then, why do you make j go from 0 to the length of the array? You compare each pair of elements twice. You should make j go from i + 1 to the length of the array (which will also avoid the i != j comparison).
Finally, you could gain a few nanoseconds by avoiding calling Math.abs() twice.
And then, you could completely change your algorithm by sorting the array first, as noted in other answers.
You can theoretically get an O(n) solution by
sorting with shell radix sort (edited, thanks to j_random_hacker for pointing it out)
one pass to find difference between numbers
Here's a question:
How long would it take to find the min distance if the array was sorted?
You should be able to finish the rest out from here.
Sorting the array first would exempt us from using another FOR loop.
public static int distclosest(int numbers[]) {
Arrays.sort(numbers);
int aSize = numbers.length;
int dMin = numbers[aSize-1];
for(int i=0; i<aSize-1; i++) {
dMin = Math.min(dMin, numbers[i+1]-numbers[i]);
}
return dMin;
}
static void MinNumber(int [] nums){
Arrays.sort(nums);
int min = nums[1] - nums[0];
int indexOne = 0 , indexTwo = 1;
for (int i = 1; i < nums.length -1; i++) {
if (min > (nums[i+1] - nums[i])) {
min = nums[i+1] - nums[i] ;
indexOne = i ;
indexTwo = i+1 ;
}
}
System.out.println("Minimum number between two values is: "+ min + " and the values is "+nums[indexOne]+" , "+nums[indexTwo] );
}
np: sorting the array is a must before executing the algorithm.
static int minDist(int arr[]) {
int firstPointer, nextPointer;
int minDistance = arr[1] - arr[0];
int tempDistance;
for (firstPointer = 0; firstPointer < arr.length; firstPointer++) {
for (nextPointer = firstPointer + 1; nextPointer < arr.length; nextPointer++) {
if (arr[nextPointer] == arr[firstPointer]) {
return 0;
} else {
tempDistance = (arr[nextPointer] - arr[firstPointer]);
if (minDistance > tempDistance) {
minDistance = tempDistance;
}
}
}
}
return minDistance;
}
public static void main(String[] args) {
int[] testArray = {1000, 1007, 3, 9, 21};
Arrays.sort(testArray);
int result = minDist(testArray);
System.out.println(result);
}

Categories

Resources