简体   繁体   中英

Recursion stackoverflow Java

I need to count the number of numbers on the right that are less than the number arr[i]. My problem is that the stack overflows at large sizes and I can't solve it in any way. Please tell me how can I refactor my code to avoid the error StackOverflow?

public class Smaller {
    public static int[] smaller(int[] unsorted) {
        int[] result = new int[unsorted.length];

        for (int i = 0; i < unsorted.length; i++) {
            result[i] = countSmaller(unsorted[i], 0, i + 1, unsorted);
        }

        return result;
    }

    private static int countSmaller(int currentNumber, int count, int index, int[] arr) {
        if (index >= arr.length) {
            return count;
        }

        return arr[index] < currentNumber
                ? countSmaller(currentNumber, count + 1, index + 1, arr)
                : countSmaller(currentNumber, count, index + 1, arr);
    }
}

I agree with comments questioning whether recursion is your best solution here, but if it's a requirement you can avoid stack overflow by chopping subproblems in half rather than whittling them down one-by-one. The logic is that the count in the remaining data will be the sum of the count in the first half plus the count in the second half of the remaining data. This reduces the stack growth from O(n) to O(log n).

Sorry for showing this in Python, but I don't have a Java compiler and I didn't want to risk non-functioning code. The following does the trick and should be easy for you to translate:

def smaller(unsorted):
    result = []
    for i in range(len(unsorted)):
        result.append(countSmaller(unsorted[i], i+1, len(unsorted)-1, unsorted))
    return result

def countSmaller(threshold, start, end, unsorted):
    if start < end:
        mid = start + (end - start) // 2    # double slash is integer division
        count = countSmaller(threshold, start, mid, unsorted)
        count += countSmaller(threshold, mid+1, end, unsorted)
        return count
    elif start == end:
        if unsorted[start] < threshold:
            return 1
    return 0

data = [10, 9, 8, 11, 7, 6]
print(smaller(data))    # [4, 3, 2, 2, 1, 0]

print(smaller([]))      # []

print(smaller([42]))    # [0]

With O(log n) stack growth, this should be able to handle ridonculously big arrays.

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