简体   繁体   中英

Recursion Problem - given array n and a number k

Given an array size n, and a positive number max(max represent the range of the numbers that we can use to place in the array).

I would like to count how many combinations of sorted numbers I can place in the array.

For example :

If n = 3, max = 2 .(the only numbers we can use is 1/2 as max is 2) so there are 4 combinations of sorted arrays

 1. {1,1,1}
 2. {1,1,2}
 3. {1,2,2}
 4. {2,2,2}

I wrote some code and succeed to pass this specific example but any other example that max > 2 doesn't return the correct answer.

the problem as I identify it is when the recursion reaches the last index it doesn't try a third number it just folds back.

my code :

private static int howManySorted(int n, int max, int index, int numToMax, int prevNum) {        
    // If the value is bigger then max return 0
    if(numToMax > max) {
        return 0;
    }
    if (numToMax < prevNum) {
        return 0;
    }
    //If Index reached the end of the array return 1
    if(index == n) {
        return 1;
    }

    int sortTwo =  howManySorted(n, max, index+1, numToMax, numToMax);
    int sortOne =  howManySorted(n, max, index+1, numToMax+1, numToMax);
    return ((sortOne+sortTwo));
}

public static int howManySorted(int n, int max) {
    return howManySorted(n, max, 0, 1, 0);
}

start with "{1," and add elements "{1,1" and/or value "{2," with each recursion. when it reach n elements array we add to the counter. n is the number of elements in the array max is the maximal value for each element. minimal is 1. element is the current cell in the array being manipulated. we start with 1 (in actual array means 0). value is the current value of the current element. we start with 1.

// external function according to the given question
public static int count (int n, int max) 
{
    return count(n,max, 1, 1);
}

private static int count (int n, int max, int element, int value) 
{
    int counter = 0;
    // only if our array reached n elements we count the comination
    if (element == n) 
        counter++;
    else // we need to continue to the next element with the same value
        counter += count(n, max, element +1, value);
    if (value < max) // if our current element didn't reach max value
        counter += count (n, max, element, value+1); 
    return counter;
}

I think you would need to change your two recursive calls (this is why it only reaches value 2) and do as many calls as your max parameter:

private static int howManySorted(int n, int max, int index, int numToMax, int prevNum) {
    // If the value is bigger then max return 0
    if (numToMax > max) {
        return 0;
    }
    if (numToMax < prevNum) {
        return 0;
    }
    //If Index reached the end of the array return 1
    if (index == n) {
        return 1;
    }

    int result = 0;
    for (int i = 0; i < max; i++)
        result += howManySorted(n, max, index + 1, numToMax + i, numToMax);

    return result;
}

I believe you can simplify your answer to something like this

private static long howManySorted(int length, int min, int max) {
    if (length == 1) {
        return max - min + 1;
    }

    // if (min == max) {
    //    return 1;
    // }

    long result = 0;
    for (int i = min; i <= max; i++) {
        result += howManySorted(length - 1, i, max);
    }
    return result;
}

public static long howManySorted(int length, int max) {
    if ((length < 1) || (max < 1)) {
        throw new IllegalArgumentException();
    }

    return howManySorted(length, 1, max);
}

Client should call the public method.

So as you can see terminate conditions are when remaining length is 1, or min reaches max . Even removing the second terminate condition doesn't change the result, but can improve the performance and number of recursions.

Just test my code, I think it figures out your problem:

class Test {
private static int howManySorted(int n, int max) {
    //Better time complexity if u use dynamic programming rather than recursion.

    if (n == 0) return 1;

    int res = 0; // "res" can be a very large.

    for (int i = n; i >= 1; i--) {
        for (int j = max; j >= 1;j--) {
            res += howManySorted(i-1, j-1);
        }
    }

    return res;
}

public static void main(String[] args) {
    System.out.println(howManySorted(3, 2));
}

}

This code will run faster if you use dynamic programming and be careful about the answer, it could be a very large integer.

You guys are forgetting he needs a solution using only recursion. Probably a Java assignment for a CS class.

I also had that question.

This is the answer I came up with:

/**
 * @param n Number of values in the array
 * @param max Maximum value of each cell in the array
 * @return int
 */
public static int howManySorted(int n, int max) {
    return howManySorted(max, max, 1, n - 1);
}

/**
 *
 * @param value The current value
 * @param max The maximum possible value (not allowed to use global parameters, so the parameter value always stays the same)
 * @param min The minimum value allowed in this index. Determined by the value of the previous index (when first called, use value 1)
 * @param index The index of the value being manipulated
 * @return
 */
public static int howManySorted(int value, int max, int min, int index) {
    //If any of these cases are found true, it means this value is invalid, don't count it
    if (index < 0 || value < min) {
        return 0;
    }
    //First lower the value in the same index, the result is the number of valid values from that branch
    int lowerValue = howManySorted(value - 1, max, min, index);
    //Now check all the valid values from the next index - value is max-1 to prevent counting twice some numbers
    int lowerIndex = howManySorted(max - 1, max, value, index - 1);
    //Return 1 (this number we are at right now) + all of its children
    return 1 + lowerValue + lowerIndex;
}

I treated each series (eg '1,1,2') as an array, so at the beginning I wrote something like that:

public static void main(String[] args)
{
    System.out.println(howManySorted(3, 2, 1, "")); // 4
    System.out.println(howManySorted(2, 3, 1, "")); // 6
}
private static int howManySorted(int n, int max, int index, String builder)
{
    if (max == 0) // if we exceeds max, return 0.
        return 0;

    if (n == 0) // num represents how many individual numbers we can have, if it is zero it means we have the required length (e.g. if n = 3, we have 'x1,x2,x3').
    {
        System.out.println(builder.substring(0, builder.length() - 2));
        return 1;
    }

    int r1 = howManySorted(n - 1, max, index, builder + index + ", "); // i added additional var 'index' to represent each number in the list: (1,1,1)
    int r2 = howManySorted(n, max - 1, index + 1, builder); // I'm increasing the index and decreasing the max (1,1,**2**)

    return r1 + r2;
}

But eventually, we don't need the 'index' nor the 'builder', they were just to emphasize how I solved it...

public static void main(String[] args)
{
    int max = 2, n = 3;
    System.out.println(howManySorted(n, max)); // 4

    int max1 = 3, n1 = 2;
    System.out.println(howManySorted(n1, max1)); // 6
}

public static int howManySorted(int n, int max)
{
    if (max == 0) // if we exceeds max, return 0.
        return 0;

    if (n == 0) // like we said, num represents how many individual numbers we can have, if it is zero it means we have the required length (e.g. if n = 3, we have 'x1,x2,x3').
        return 1;

    int r1 = howManySorted(n - 1, max);
    int r2 = howManySorted(n, max - 1);

    return r1 + r2;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM