• 每日一题 1458两个子序列的最大点积


    题目

    题目
    给你两个数组 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] 。
    它们的点积为 (23 + (-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

    题解

    记忆化搜索

    class Solution {
        private int[] nums1, nums2;
        private int[][] cache;
        private int mk = Integer.MIN_VALUE;
    
        public int maxDotProduct(int[] nums1, int[] nums2) {
            this.nums1 = nums1;
            this.nums2 = nums2;
            int n1 = nums1.length, n2 = nums2.length;
            cache = new int[n1][n2];
            for (int i = 0; i < n1; i++) {
                Arrays.fill(cache[i],-1);
            }
            //答案可能存在负数
            return dfs(n1 - 1, n2 - 1) > 0 ? dfs(n1 - 1, n2 - 1) : mk;
        }
    
        public int dfs(int i, int j) {
            if (i < 0 || j < 0) {
                return 0;
            }
            if (cache[i][j] != -1) {
                return cache[i][j];
            }
            int k = nums1[i] * nums2[j];
            mk = Math.max(mk, k);
            return cache[i][j] = Math.max(Math.max(dfs(i - 1, j), dfs(i, j - 1)), dfs(i - 1, j - 1) + k);
        }
    }
    
    • 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

    递推

    class Solution {
        public int maxDotProduct(int[] nums1, int[] nums2) {
            int n1 = nums1.length, n2 = nums2.length;
            int mk = Integer.MIN_VALUE;
            int[][] f = new int[n1 + 1][n2 + 1];
            for (int i = 0; i < n1; i++) {
                for (int j = 0; j < n2; j++) {
                    int k = nums1[i] * nums2[j];
                    mk = Math.max(k, mk);
                    f[i + 1][j + 1] = Math.max(Math.max(f[i][j + 1], f[i + 1][j]), f[i][j] + k);
                }
            }
            return f[n1][n2] > 0 ? f[n1][n2] : mk;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    空间优化

    class Solution {
        public int maxDotProduct(int[] nums1, int[] nums2) {
            int n2 = nums2.length;
            int mk = Integer.MIN_VALUE;
            int[] f = new int[n2 + 1];
            for (int x : nums1) {
                int pre = f[0];
                for (int j = 0; j < n2; j++) {
                    int temp = f[j + 1];
                    int k = x * nums2[j];
                    mk = Math.max(k, mk);
                    f[j + 1] = Math.max(Math.max(f[j + 1], f[j]), pre + k);
                    pre = temp;
                }
            }
            return f[n2] > 0 ? f[n2] : mk;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    Linux内存管理(十):备选区域初始化
    The specified module could not be found.
    【Java基础篇】逻辑控制
    时间戳 太平洋夏令时间和本地时间相互转换及自定义夏令时
    2535. 数组元素和与数字和的绝对差
    【解惑】孜孜不倦,用足球赛程详解c#中的yield return用法
    SI3262—高度集成的低功耗SOC读卡器芯片
    笔记本电脑windows10有线连接开无线热点方法已经成功
    linux---man
    【Linux】软件包管理器yum和编辑器vim(内附动图)
  • 原文地址:https://blog.csdn.net/fffffall/article/details/133777557