观光景点组合得分问题详细讲解(Java) | 豆包MarsCode AI刷题

54 阅读2分钟

一、题目描述

小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。

一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。

小R想知道,在哪种情况下能够获得观光景点组合的最高得分。

二、测试样例

样例1:

输入:values = [8, 3, 5, 5, 6]
输出:11

样例2:

输入:values = [10, 4, 8, 7]
输出:16

样例3:

输入:values = [1, 2, 3, 4, 5]
输出:8

三、思路解析

3.1 暴力求解

遍历所有可能的组合,取最大值,时间复杂度N2

3.2 动态规划

标签是动态规划,肯定要用到动态规划 分别使用两个和values相同大小的一维数组 int[] dpLeftint[] dpRight 来存储指定位置前面最大的值和后面最小的值

举例来说,dpLeft[5], 表示数组values[5]前6个数中(含values[5]), 可以利用的最大的值(该值已经经过了距离衰减的计算

dpRight[5],表示数组values[5]后面所有的数中(不含values[5]), 可以利用的最大的值(该值已经经过了距离衰减的计算

需要注意的是,两个dp数组哪个含当前下标不是固定的,只要保证一个含,另一个不含即可

3.2.1 数组的初始化

左dp数组的左边界的第一个元素直接设置成 values数组的左边界, 右dp数组的右边界设置成0

3.2.2 特殊情况

当数组元素个数小于等于1的时候,直接返回0,因为找不出来一对组合

3.2.3 递推公式

记录右边的衰减最大值,没往右走一步,就衰减1,将衰减之后的值和当前的values[i]进行对比,取最大值, 并将衰减最大值再更新成最大值。

for (int i = 1; i < values.length; i++) {
    dpLeft[i] = Math.max(values[i], dplTmep-1);
    dplTmep = dpLeft[i];
}

3.2.4 最后遍历

最后构造完dp数组之后,只需要从头开始进行遍历,持续搜索 Max(dpRight[i] + dpLeft[i]),返回最后的结果即可

四、最终代码

import java.util.Arrays;

public class Main {
    public static int solution(int[] values) {
        if(values.length <= 1){
            return 0;
        }
        // write code here
        int[] dpLeft = new int[values.length];
        dpLeft[0] = values[0];
        int dplTmep = dpLeft[0];
        int[] dpRight = new int[values.length];
        int dprTmep = Integer.MIN_VALUE+1;
        for (int i = 1; i < values.length; i++) {
            dpLeft[i] = Math.max(values[i], dplTmep-1);
            dplTmep = dpLeft[i];
        }
        dpRight[values.length-1] = 0;
        for (int i = dpRight.length - 2; i >= 0; i--) {
            dpRight[i] = Math.max(dprTmep-1, values[i+1]-1);
            dprTmep = dpRight[i];
        }
        int re = 0;
        for (int i = 0; i < dpRight.length; i++) {
            re = Math.max(re, dpLeft[i]+dpRight[i]);
        }
        return re; // Placeholder return
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{8, 3, 5, 5, 6}) == 11 ? 1 : 0);
        System.out.println(solution(new int[]{10, 4, 8, 7}) == 16 ? 1 : 0);
        System.out.println(solution(new int[]{1, 2, 3, 4, 5}) == 8 ? 1 : 0);
    }
}