Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

README.md

Given two arrays nums1 and nums2.

Return the maximum dot product between non-empty subsequences of nums1 and nums2 with the same length.

A subsequence of a array is a new array which is formed from the original array by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, [2,3,5] is a subsequence of [1,2,3,4,5] while [1,5,3] is not).

 

Example 1:

Input: nums1 = [2,1,-2,5], nums2 = [3,0,-6]
Output: 18
Explanation: Take subsequence [2,-2] from nums1 and subsequence [3,-6] from nums2.
Their dot product is (2*3 + (-2)*(-6)) = 18.

Example 2:

Input: nums1 = [3,-2], nums2 = [2,-6,7]
Output: 21
Explanation: Take subsequence [3] from nums1 and subsequence [7] from nums2.
Their dot product is (3*7) = 21.

Example 3:

Input: nums1 = [-1,-1], nums2 = [1,1]
Output: -1
Explanation: Take subsequence [-1] from nums1 and subsequence [1] from nums2.
Their dot product is -1.

 

Constraints:

  • 1 <= nums1.length, nums2.length <= 500
  • -1000 <= nums1[i], nums2[i] <= 1000

Related Topics:
Dynamic Programming

Solution 1. DP

Let dp[i + 1][j + 1] be the answer to the subproblem on s[0..i] and t[0..j].

For dp[0][i] and dp[i][0], they mean that either s or t is empty array. Since the question is asking for non-empty subsequences, they are not valid cases, so we should regard them as -INF.

For dp[i + 1][j + 1], we have three choices:

  • We include s[i] and t[j] in the subsequences. We get max(0, dp[i][j]) + s[i] * t[j].
  • We ignore s[i] and reuse the result of dp[i][j + 1].
  • We ignore t[j] and reuse the result of dp[i + 1][j].
dp[i + 1][j + 1] = max(
                        max(0, dp[i][j]) + s[i] * t[j],   // If we include s[i] and t[j] in the subsequences
                        dp[i][j + 1],                     // If we don't include s[i] in the subsequence
                        dp[i + 1][j]                      // If we don't include t[j] in the subsequence
                      )
dp[0][i] = dp[i][0] = -INF 
// OJ: https://leetcode.com/problems/max-dot-product-of-two-subsequences/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
class Solution {
public:
    int maxDotProduct(vector<int>& s, vector<int>& t) {
        int M = s.size(), N = t.size();
        vector<vector<int>> dp(M + 1, vector<int>(N + 1, INT_MIN));
        for (int i = 0; i < M; ++i) {
            for (int j = 0; j < N; ++j) {
                dp[i + 1][j + 1] = max({ max(0, dp[i][j]) + s[i] * t[j], dp[i + 1][j], dp[i][j + 1] });
            }
        }
        return dp[M][N];
    }
};

Solution 2. DP with Space Optimization

Since dp[i + 1][j + 1] only depends on dp[i][j], dp[i + 1][j] and dp[i][j + 1], we can reduce the size of the dp array from M * N to 1 * N.

// OJ: https://leetcode.com/problems/max-dot-product-of-two-subsequences/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(min(M, N))
class Solution {
public:
    int maxDotProduct(vector<int>& s, vector<int>& t) {
        int M = s.size(), N = t.size();
        if (M < N) swap(M, N), swap(s, t);
        vector<int> dp(N + 1, INT_MIN);
        for (int i = 0; i < M; ++i) {
            int prev = INT_MIN;
            for (int j = 0; j < N; ++j) {
                int cur = dp[j + 1];
                dp[j + 1] = max({ max(0, prev) + s[i] * t[j], dp[j], dp[j + 1] });
                prev = cur;
            }
        }
        return dp[N];
    }
};