简体   繁体   English

给定一个整数数组和一个总和,任务是找出给定数组的子集是否存在总和等于给定总和的子集

[英]Given an array of integers and a sum, the task is to find if there exists a subsets of given array with sum equal to given sum

Here is the function that i have written.这是我写的函数。

    public static boolean existsSum(int[] arr, int n, int sum){
            if(sum==0)
                return true;
            if(n<=0)
                return false;
            if(arr[n-1] == sum)
                return true;
            if(sum<0)
                return false;
            if(sum<arr[n-1])
                return existsSum(arr, n-1,sum);
            return existsSum(arr, n-1, sum-arr[n-1])  || existsSum(arr, n-1,sum)  ;
        }

This works perfectly fine.这工作得很好。 But as soon as I change last line of code like this但是一旦我像这样更改最后一行代码

    public static boolean existsSum(int[] arr, int n, int sum){
            if(sum==0)
                return true;
            if(n<=0)
                return false;
            if(arr[n-1] == sum)
                return true;
            if(sum<0)
                return false;
            if(sum<arr[n-1])
                return existsSum(arr, n-1,sum);
            return existsSum(arr, n-1,sum) || existsSum(arr, n-1, sum-arr[n-1])  ;
        }

It exceeds the time limit.它超过了时间限制。 I can't understand what is the impact on execution time upon changing the sequence.我无法理解更改序列对执行时间有何影响。 Please help.请帮忙。

Note the fact that ||请注意|| is short-circuiting ie in a || b是短路的,即在a || b a || b , if a is true, b is not evaluated. a || b ,如果a为真,则不评估b

The difference between the two operands of || ||两个操作数的区别is that existsSum(arr, n-1, sum-arr[n-1]) "adds" the current item to the list of items that sums to the total sum, while existsSum(arr, n-1, sum) doesn't.existsSum(arr, n-1, sum-arr[n-1])将当前项“添加”到总和为总和的项列表中,而existsSum(arr, n-1, sum)没有'吨。

In the first code snippet, if existsSum(arr, n-1, sum-arr[n-1]) is true, existsSum(arr, n-1, sum) is not even called.在第一个代码片段中,如果existsSum(arr, n-1, sum-arr[n-1])为真,则existsSum(arr, n-1, sum)甚至不会被调用。 Imagine I call this with the array [1,2,3] and the sum 6. The first operand is going to return true every recursive call, and there is no need to evaluate the second operand.想象一下,我用数组[1,2,3]和总和 6 调用它。第一个操作数将在每次递归调用时返回 true,并且不需要评估第二个操作数。

Similarly, in the second code snippet, existsSum(arr, n-1, sum) is run first, and if true, existsSum(arr, n-1, sum-arr[n-1]) is not called.类似地,在第二个代码片段中, existsSum(arr, n-1, sum) ,如果为真, existsSum(arr, n-1, sum-arr[n-1]) However, existsSum(arr, n-1, sum) can rarely return true on its own .但是, existsSum(arr, n-1, sum)很少会自行返回 true 。 What I mean by this is that for the call existsSum(arr, n-1, sum) to return true, the value true must have come from a recursive call to existsSum(arr, n-1, sum-arr[n-1]) .我的意思是,要使调用existsSum(arr, n-1, sum)返回true,则值true必须来自对existsSum(arr, n-1, sum-arr[n-1])的递归调用existsSum(arr, n-1, sum-arr[n-1]) You can verify this by analysing the different branches.您可以通过分析不同的分支来验证这一点。 (the two branches that return true are sum==0 and arr[n-1] == sum . Hopefully you'll agree both are rare) This means that backtracking (ie calling existsSum(arr, n-1, sum-arr[n-1]) ) will definitely happen for existsSum(arr, n-1, sum) . (返回 true 的两个分支是sum==0arr[n-1] == sum 。希望你会同意两者都是罕见的)这意味着回溯(即调用existsSum(arr, n-1, sum-arr[n-1]) ) 肯定会发生existsSum(arr, n-1, sum)


In the worst case though, these two code snippets are the same.但在最坏的情况下,这两个代码片段是相同的。

This should be O(n)这应该是 O(n)

public static boolean sumExists(int [] in, int sum) {
    //You might be able to get away with just sorting the values and not copying it.
    int [] input = Arrays.copyOf(in, in.length);
    Arrays.sort(input);
    int currentSum = 0;
    int startIdx = 0;
    for (int i = 0; i < input.length; i++) {
        if (currentSum > sum) {
            while (currentSum > sum && startIdx < i) {
                currentSum -= input[startIdx++];
            }
        }

        if (currentSum == sum) {
            return true;
        } 
        currentSum += input[i];
    }
    return false;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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