【區間 dp】A012_LC_兩個子序列的最大點積(分類討論)

一、Problem

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).

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.

二、Solution

方法一:dp

兩個序列取別名爲 A、B

  • 定義狀態
    • dp[i][j]dp[i][j] 表示取 A 中的前 ii 個數字和 B 中的前 jj 個數字可以組成的最大點積和。
  • 思考初始化:
    • dp[i][j]=INFdp[i][j] = -INF,因爲系列存在負數,所以結果可能爲負數。
  • 思考狀態轉移方程
    • dp[i][j] = A[i] × B[j],只選擇 A、B 當前的兩個數,不選其它數
    • dp[i][j] = max(dp[i][j], dp[i-1][j]),只選 B 的第 jj 個數
    • dp[i][j] = max(dp[i][j], dp[i][j-1]),只選 A 的第 ii 個數
    • dp[i][j] = max(dp[i][j], dp[i-1][j-1] + A[i] × B[j]),選擇 A、B 當前的兩個數和前面的選的數組成的最長點積和。
  • 思考輸出dp[n1][n2]dp[n1][n2]
class Solution {
    public int maxDotProduct(int[] A, int[] B) {
        int n1 = A.length, n2 = B.length;
        int max = 0, INF = -0x3f3f3f3f, dp[][] = new int[n1+1][n2+1];
        for (int i = 0; i <= n1; i++)
        for (int j = 0; j <= n2; j++)
            dp[i][j] = INF;
        
        for (int i = 1; i <= n1; i++)
        for (int j = 1; j <= n2; j++) {
            int pro =  A[i-1]*B[j-1];
            dp[i][j] = pro;
            dp[i][j] = Math.max(dp[i][j], dp[i-1][j]);
            dp[i][j] = Math.max(dp[i][j], dp[i][j-1]);
            dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1] + pro);
        }
        return dp[n1][n2];
    }
}

複雜度分析

  • 時間複雜度:O(n1×n2)O(n1 × n2)
  • 空間複雜度:O(n1×n2)O(n1 × n2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章