当前位置:   article > 正文

力扣题312戳气球_有 n个气球,编号为1到n,每个气球上都标有一个数字,用数组balls来存储这些数字。

有 n个气球,编号为1到n,每个气球上都标有一个数字,用数组balls来存储这些数字。

有 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

1.自己的解法:想用回溯法,把每种和都计算出来,然后取最大值。

        这种方法可以通过测试用例,但是提交后显示超出时间限制。因为使用这种回溯法,会造成

      大量的重复计算。

  1. class Solution {
  2. int maxCount = 0;//记录最大值
  3. public int maxCoins(int[] nums) {
  4. boolean[] isVisited = new boolean[nums.length];//存储每个气球的状态,是否被戳破
  5. maxCoins(nums,isVisited,0,0);
  6. return maxCount;
  7. }
  8. public void maxCoins(int[] nums,boolean[] isVisited,int curCount,int length) {
  9. if (length == nums.length) {//所有气球都被戳皮后,比较是否需要更新最大值
  10. maxCount = Math.max(maxCount,curCount);
  11. return;
  12. }
  13. for (int i = 0;i < nums.length;i++) {//遍历每种情况
  14. int curNum = curNum(nums,isVisited,i);//计算当前气球被戳破的话可以得到多少硬币
  15. if (!isVisited[i]) {//如果当前气球没有被戳破过
  16. curCount += curNum;//加上硬币数
  17. isVisited[i] = true;//更新气球状态
  18. maxCoins(nums,isVisited,curCount,length + 1);
  19. } else{//如果当前气球被戳破了,直接跳过
  20. continue;
  21. }
  22. //回溯
  23. isVisited[i] = false;
  24. curCount -= curNum;
  25. }
  26. }
  27. //该函数用来计算每个气球被戳破的话能够得到多少硬币
  28. public int curNum(int[] nums,boolean[] isVisited,int index) {
  29. int left = index - 1;
  30. int right = index + 1;
  31. while (left >= 0 && isVisited[left]) {//找到左侧第距离最近的未被戳破的气球
  32. left--;
  33. if (left < 0) {
  34. break;
  35. }
  36. }
  37. while (right <= nums.length - 1 && isVisited[right]) {//找到右侧距离最近的未被戳破的气球
  38. right++;
  39. if (right > nums.length - 1) {
  40. break;
  41. }
  42. }
  43. if (left < 0 && right > nums.length - 1) {//左右不存在未戳破的气球的情况
  44. return 1 * nums[index] * 1;
  45. } else if (left < 0) {//只有左侧气球被戳破的情况
  46. return 1 * nums[index] * nums[right];
  47. } else if (right > nums.length - 1) {//只有右侧气球被戳破的情况
  48. return nums[left] * nums[index] * 1;
  49. } else {//两侧气球均未被戳破的情况
  50. return nums[left] * nums[index] * nums[right];
  51. }
  52. }
  53. }

2.题解:为了方便处理,我们对nums数组稍作处理,将其两边各加上题目中假设存在的 nums[−1] 和nums[n] ,并保存在val 数组中,即]val[i]=nums[i−1] 。之所以这样处理是为了处理nums[−1] ,防止下标越界。

        记忆化搜索:

  1. class Solution {
  2. public int[][] rec;//存储每个区间的最大值
  3. public int[] val;//存储每个气球值
  4. public int maxCoins(int[] nums) {
  5. int n = nums.length;
  6. val = new int[n + 2];
  7. val[0] = val[n + 1] = 1;//在开头和末尾各自加上一个1,方便计算
  8. for (int i = 1;i <= n;i++) {
  9. val[i] = nums[i - 1];
  10. }
  11. rec = new int[n+2][n+2];
  12. for (int i = 0;i <= n + 1;i++) {
  13. Arrays.fill(rec[i],-1);
  14. }
  15. return solve(0,n+1);
  16. }
  17. public int solve(int left,int right) {
  18. if (left >= right - 1) {//表示所有气球都被戳完了
  19. return 0;
  20. }
  21. if (rec[left][right] != -1) { // 这个区间的最大值之前已经计算过了,直接返回,避免重复计算
  22. return rec[left][right];
  23. }
  24. for (int i = left + 1;i < right;i++) {
  25. int sum = val[left] * val[i] * val[right];//当前气球被戳破的到的硬币数
  26. sum += solve(left,i) + solve(i,right);//递归计算左侧最大和与右侧最大和
  27. rec[left][right] = Math.max(rec[left][right],sum);//更新当前区间的最大值
  28. }
  29. return rec[left][right];
  30. }
  31. }

        动态规划

  1. class Solution {
  2. public int maxCoins(int[] nums) {
  3. int n = nums.length;
  4. int[] val = new int[n + 2];
  5. val[0] = val[n + 1] = 1;//在开头和末尾各自加上一个1,方便计算
  6. for (int i = 1;i <= n;i++) {
  7. val[i] = nums[i - 1];
  8. }
  9. int[][] rec = new int[n+2][n+2]; //开区间
  10. //i从末端开始,为了从小区间得到大区间
  11. for (int i = n - 1;i >= 0;i--) {//开区间左侧起点
  12. for (int j = i + 2;j <= n + 1;j++) {//右侧中点
  13. for (int k = i + 1;k < j;k++) {//这个开区间的中间值
  14. int sum = val[i] * val[k] * val[j];
  15. sum += rec[i][k] + rec[k][j];
  16. rec[i][j] = Math.max(rec[i][j],sum);
  17. }
  18. }
  19. }
  20. return rec[0][n + 1];
  21. }
  22. }

题源:力扣

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/717693
推荐阅读
相关标签
  

闽ICP备14008679号