【LetMeFly】1458.两个子序列的最大点积:动态规划 力扣题目链接:https://leetcode.cn/problems/max-dot-product-of-two-subsequences/
给你两个数组 nums1 和 nums2 。
请你返回 nums1 和 nums2 中两个长度相同的 非空 子序列的最大点积。
数组的非空子序列是通过删除原数组中某些元素(可能一个也不删除)后剩余数字组成的序列,但不能改变数字间相对顺序。比方说,[2,3,5] 是 [1,2,3,4,5] 的一个子序列而 [1,5,3] 不是。
示例 1:
输入: nums1 = [2,1,-2,5], nums2 = [3,0,-6]
输出: 18
解释: 从 nums1 中得到子序列 [2,-2] ,从 nums2 中得到子序列 [3,-6] 。
它们的点积为 (2*3 + (-2)*(-6)) = 18 。
示例 2:
输入: nums1 = [3,-2], nums2 = [2,-6,7]
输出: 21
解释: 从 nums1 中得到子序列 [3] ,从 nums2 中得到子序列 [7] 。
它们的点积为 (3*7) = 21 。
示例 3:
输入: nums1 = [-1,-1], nums2 = [1,1]
输出: -1
解释: 从 nums1 中得到子序列 [-1] ,从 nums2 中得到子序列 [1] 。
它们的点积为 -1 。
提示:
1 <= nums1.length, nums2.length <= 500
-1000 <= nums1[i], nums2[i] <= 100
点积:
定义 a = [a 1 , a 2 ,…, a n ] 和 b = [b 1 , b 2 ,…, b n ] 的点积为:
这里的 Σ 指示总和符号。
解题方法:动态规划 令dp[i][j]表示nums1[0..i]与nums2[0..j]的子序列最大点积,那么则有状态转移方程:
1 2 3 4 5 6 dp[i][j] = max ( nums1[i] * nums1[j], dp[i-1 ][j], dp[i][j-1 ], dp[i-1 ][j-1 ] + nums1[i]*nums1[j] )
上述转移方程包含了所有$nums1[i]$与$nums2[j]$相乘和不相乘的情况。
时间复杂度$O(len(nums1)\times len(nums2))$
空间复杂度$O(len(nums1)\times len(nums2))$
当然,为了减少对$i-1$是否越界的判断,也可以给dp数组多开辟一行一列的空间,但注意这样的话多开辟那一行一列空间的初始值要小于等于$-10^6$(单个$nums1[i]\times nums2[j]最小值)。
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : int maxDotProduct (vector<int >& nums1, vector<int >& nums2) { int n = nums1. size (), m = nums2. size (); vector<vector<int >> dp (n, vector <int >(m)); for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < m; j++) { dp[i][j] = nums1[i] * nums2[j]; if (i) { dp[i][j] = max (dp[i][j], dp[i - 1 ][j]); } if (j) { dp[i][j] = max (dp[i][j], dp[i][j - 1 ]); } if (i && j) { dp[i][j] = max (dp[i][j], dp[i - 1 ][j - 1 ] + nums1[i] * nums2[j]); } } } return dp[n - 1 ][m - 1 ]; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 ''' LastEditTime: 2026-01-08 09:29:41 ''' from typing import List class Solution : def maxDotProduct (self, nums1: List [int ], nums2: List [int ] ) -> int : dp = [[-1000000000 ] * (len (nums2) + 1 ) for _ in range (len (nums1) + 1 )] for i, x in enumerate (nums1, 1 ): for j, y in enumerate (nums2, 1 ): dp[i][j] = max (x * y, dp[i-1 ][j], dp[i][j-1 ], dp[i-1 ][j-1 ] + x * y) return dp[-1 ][-1 ]
Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.Arrays;class Solution { public int maxDotProduct (int [] nums1, int [] nums2) { int n = nums1.length, m = nums2.length; int [][] dp = new int [n+1 ][m+1 ]; for (int i = 0 ; i <= n; i++) { Arrays.fill(dp[i], -1000000 ); } for (int i = 1 ; i <= n; i++) { for (int j = 1 ; j <= m; j++) { dp[i][j] = Math.max(nums1[i-1 ] * nums2[j-1 ], Math.max(dp[i-1 ][j], Math.max(dp[i][j - 1 ], dp[i-1 ][j-1 ] + nums1[i-1 ] * nums2[j-1 ]))); } } return dp[n][m]; } }
Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainfunc max1458_2 (a, b int ) int { if a > b { return a } return b }func max1458 (a, b, c, d int ) int { return max1458_2(a, max1458_2(b, max1458_2(c, d))) }func maxDotProduct (nums1 []int , nums2 []int ) int { n, m := len (nums1), len (nums2) dp := make ([][]int , n + 1 ) for i := range dp { dp[i] = make ([]int , m + 1 ) for j := range dp[i] { dp[i][j] = -1000000 ; } } for i, x := range nums1 { for j, y := range nums2 { dp[i+1 ][j+1 ] = max1458(x*y, dp[i][j+1 ], dp[i+1 ][j], dp[i][j] + x*y) } } return dp[n][m] }
Rust 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 impl Solution { pub fn max_dot_product (nums1: Vec <i32 >, nums2: Vec <i32 >) -> i32 { let n : usize = nums1.len (); let m : usize = nums2.len (); let mut dp : Vec <Vec <i32 >> = vec! [vec! [-1000000 ; m+1 ]; n+1 ]; for i in 1 ..=n { for j in 1 ..=m { dp[i][j] = dp[i-1 ][j].max (dp[i][j-1 ].max ((nums1[i-1 ] * nums2[j-1 ]).max (dp[i-1 ][j-1 ] + nums1[i-1 ] * nums2[j-1 ]))); } } dp[n][m] } }
同步发文于CSDN 和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~
千篇源码题解已开源