<p>You are given a <strong>0-indexed</strong> array of integers <code>nums</code>, and an integer <code>target</code>.</p>

<p>Return <em>the <strong>length of the longest subsequence</strong> of</em> <code>nums</code> <em>that sums up to</em> <code>target</code>. <em>If no such subsequence exists, return</em> <code>-1</code>.</p>

<p>A <strong>subsequence</strong> is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,2,3,4,5], target = 9
<strong>Output:</strong> 3
<strong>Explanation:</strong> There are 3 subsequences with a sum equal to 9: [4,5], [1,3,5], and [2,3,4]. The longest subsequences are [1,3,5], and [2,3,4]. Hence, the answer is 3.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> nums = [4,1,3,2,1,5], target = 7
<strong>Output:</strong> 4
<strong>Explanation:</strong> There are 5 subsequences with a sum equal to 7: [4,3], [4,1,2], [4,2,1], [1,1,5], and [1,3,2,1]. The longest subsequence is [1,3,2,1]. Hence, the answer is 4.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,1,5,4,5], target = 3
<strong>Output:</strong> -1
<strong>Explanation:</strong> It can be shown that nums has no subsequence that sums up to 3.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= nums.length &lt;= 1000</code></li>
	<li><code>1 &lt;= nums[i] &lt;= 1000</code></li>
	<li><code>1 &lt;= target &lt;= 1000</code></li>
</ul>

class Solution:
    def lengthOfLongestSubsequence(self, nums: List[int], target: int) -> int:

        # these are just impossible cases, so we can exit early                   
        if sum(nums) < target:
            return -1
        if min(nums) > target:
            return -1
    
        # trying to optimize, (saves about 1 sec on tests) - sort and remove
        # numbers larger than target from nums. They are all positive so they
        # won't be in the sub sequence
        nums.sort()
        nums = nums[0:bisect_right(nums, target)]
        
        # one more than max in description
        max_allowed = 1001

        n = len(nums)
        
        # dp[i][j] is the length of the sub seq ending on i
        # that makes target j
        dp = [[-max_allowed]*max_allowed for _ in range(n)]

        
        def sub_seq(i, new_target):
            
            # end - target is zero so we are done
            if new_target == 0:
                return 0
    
            # this means takeing the element was more than sum
            if new_target < 0 or i >= n:
                return -max_allowed
            
            # check if we have seen this before (how to find
            # new_target ending at i element)
            if dp[i][new_target] != -max_allowed:
                return dp[i][new_target]
            
            # max length if we take i or don't take i
            dont_take = sub_seq(i + 1, new_target)
            take = sub_seq(i + 1, new_target - nums[i]) + 1

            # save it to look up later
            dp[i][new_target] = max(take, dont_take)
            
            return dp[i][new_target]
    
        ans = sub_seq(0, target) 
        
        return ans if ans > -1 else -1
127237