分区相等子集总和自上而下TLE

时间:2019-06-25 12:07:37

标签: java algorithm recursion dynamic-programming

我正在解决Partition Equal Subset Sum的leetcode。

问题状态:

Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.

Note:

Each of the array element will not exceed 100.
The array size will not exceed 200.

我将以下代码写为

class Solution {
public boolean canPartition(int[] nums) {
    int sum=0;
    for(int i=0;i<nums.length;i++)
    {
        sum=sum+nums[i];
    }
    if(sum%2!=0)
    {
        return false;
    }

    int target=sum/2;
    return helper(nums,target,nums.length);

}
boolean helper(int nums[],int sum,int n)
{
    if(sum==0)
    {
        return true;
    }
    if(sum<0)
    {
        return false;
    }
    if(n==0)
    {
        return false;
    }
    return helper(nums,sum-nums[n-1],n-1)||helper(nums,sum,n-1);
}


 }

请注意,我没有包含该条件

if(sum<nums[n-1])
{
return false;
}

在我包括的基本情况下

if(sum<0)
    {
        return false;
    }

这与将只添加1个递归调用然后返回false相同。

此代码适用于89个测试用例,但给出

的TLE错误
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,100]

现在,如果修改相同的代码并包含

if(sum<nums[n-1])
    {
    return false;
    }

并删除

if(sum<0)
    {
        return false;
    }

class Solution {
public boolean canPartition(int[] nums) {
    int sum=0;
    for(int i=0;i<nums.length;i++)
    {
        sum=sum+nums[i];
    }
    if(sum%2!=0)
    {
        return false;
    }

    int target=sum/2;
    return helper(nums,target,nums.length);

}
boolean helper(int nums[],int sum,int n)
{
    if(sum==0)
    {
        return true;
    }

    if(n==0)
    {
        return false;
    }
    if(nums[n-1]>sum)
    {
        return false;
    }

    return helper(nums,sum-nums[n-1],n-1)||helper(nums,sum,n-1);
}
}

该代码可以正常工作并通过所有测试用例。

由于两个代码都相同,那么一个额外的递归调用如何给我TLE? 还有别的吗?

1 个答案:

答案 0 :(得分:0)

测试用例确实很弱。第一个应该获得TLE,因为您没有使用动态编程,但是执行了简单的回溯。第二个应该得到WA。如果使用记忆,则复杂度为O( totalSum * arraySize),但代码的复杂度为O(2 ^ arraySize)。

现在观察您在每种状态下都有两个选择。您是否选择元素。即使此条件为if(nums[n-1]>sum),第二个选项仍然有效-继续不选择项目。但是您的第二个代码会忽略这种情况的两种情况,从而将调用减少到解决方案所需的时间少于1毫秒,这比大多数正确的解决方案要快。由于第二个解决方案没有反测试用例,因此它通过了。