• 【LeetCode】戳气球 [H](记忆化搜索)


    312. 戳气球 - 力扣(LeetCode)

    一、题目

    有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

    现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。

    求所能获得硬币的最大数量。

    示例 1:
    输入:nums = [3,1,5,8]
    输出:167
    解释:
    nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
    coins =  3*1*5    +   3*5*8   +  1*3*8  + 1*8*1 = 167

    示例 2:
    输入:nums = [1,5]
    输出:10

    提示:

    • n == nums.length
    • 1 <= n <= 300
    • 0 <= nums[i] <= 100

    二、代码

    1. class Solution {
    2. public int maxCoins(int[] nums) {
    3. // 我们将数组扩大两个位置,用来表示原本左右两个边界,这样可以在写代码的过程中减少很多的边界条件讨论
    4. int[] arr = new int[nums.length + 2];
    5. // 将左边界设置为1
    6. arr[0] = 1;
    7. // 将右边界设置为1
    8. arr[nums.length + 1] = 1;
    9. // 将原数组中的数转移到新数组
    10. for (int i = 1; i <= nums.length; i++) {
    11. arr[i] = nums[i - 1];
    12. }
    13. // 加缓存
    14. int dp[][] = new int[nums.length + 2][nums.length + 2];
    15. return process(1, nums.length, arr, dp);
    16. }
    17. public int process(int l, int r, int[] arr, int[][] dp) {
    18. // 如果已经计算过这个结果,直接返回
    19. if (dp[l][r] != 0) {
    20. return dp[l][r];
    21. }
    22. // 如果arr[L..R]范围上只有一个气球,直接打爆即可
    23. if (l == r) {
    24. return arr[l - 1] * arr[l] * arr[r + 1];
    25. }
    26. // 选择一:让l位置最后爆 当l最后爆的时候,它左右两边距离最近的并且没有爆掉的就是l-1和r+1,因为这个函数保证了l-1和r+1一定没有爆。并且在l+1~r这个范围内,能保证左边界l和右边界r+1一定没有爆,这样就可以调preocess函数了。
    27. int coins1 = arr[l - 1] * arr[l] * arr[r + 1] + process(l + 1, r, arr, dp);
    28. // 选择二:让r位置最后爆
    29. int coins2 = arr[l - 1] * arr[r] * arr[r + 1] + process(l, r - 1, arr, dp);
    30. int max = coins1 > coins2 ? coins1 : coins2;
    31. // 选择三:尝试让l~r之间的位置最后爆
    32. for (int i = l + 1; i < r ; i++) {
    33. // 这个最后爆的位置就将整个区间分成了两份,并且左右两个分出来的区间都能满足左右两个边界没有爆,所以可以调用preocess函数
    34. int coins3 = arr[l - 1] * arr[i] * arr[r + 1] + process(l, i - 1, arr, dp) + process(i + 1, r, arr, dp);
    35. max = coins3 > max ? coins3 : max;
    36. }
    37. // 记录下结果缓存
    38. dp[l][r] = max;
    39. // 将所有可能的选择方案中选择得分最多的一个返回
    40. return max;
    41. }
    42. }

    三、解题思路 

    关键在于递归函数如何设计,就设定preocess方法是求arr[L...R]打爆所有气球,最大得分是什么,并且此时[L-1] 和 [R+1]位置的气球一定没有爆。

  • 相关阅读:
    信号完整性分析基础知识之有损传输线、上升时间衰减和材料特性(十):有损传输线在时域中的表现
    Maven基础知识
    踩点记录-_-!!!
    C学生管理系统 据学号查找学生节点
    Android源码分析 - Framework层的Binder(客户端篇)
    C++实现enum反射,类似magic_enum,支持enum classes
    Qt Creator 使用技巧
    spirngcloud服务治理(注册中心)
    高保真神经网络音频编码器
    安全运营中心自动化究竟是好还是坏
  • 原文地址:https://blog.csdn.net/cy973071263/article/details/127091137