LeetCode--戳气球

链接:https://leetcode-cn.com/problems/burst-balloons/

 

题目:

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

  现在要求戳破所有的气球。每当戳破一个气球 i 时,可以获得 nums[left] * nums[i] * nums[right] 个硬币,其中 left 和 right 代表和 i 相邻的两个气球的序号,注意当戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球,

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

  说明:

    可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

 

解题思路:

解法一,我的想法是通过递归回溯来找到所能获取的最大数量的硬币,然而提交后提示时间超时,这种方法的时间复杂度达到了O(N!),其中N为气球的个数

 1 import java.util.List;
 2 import java.util.ArrayList;
 3 
 4 public class Solution {
 5     public int maxCoins(int[] nums) {
 6         List<Integer> arr = new ArrayList();
 7         for(int i = 0; i < nums.length; i++) {
 8             arr.add(nums[i]);
 9         }
10         return helper(arr);
11     }
12 
13     public int helper(List<Integer> arr) {
14         if(arr.size() == 0) return 0;
15         int pre = 0, next = 0;
16         int max = 0;
17         int len = arr.size();
18         for(int i = 0; i < len; i++) {
19             pre = i == 0 ? 1 : arr.get(i - 1); 
20             next = i == arr.size()-1 ? 1 : arr.get(i + 1); 
21             int cur = arr.get(i);
22             arr.remove(i);
23             max = Math.max(max, pre*cur*next + helper(arr));
24             arr.add(i, cur);
25         }
26         return max;
27     }
28 }

  时间复杂度:O(N!);空间复杂度:O(N),其中N为气球的个数

解法二看这里),随机选取一点作为分界点,先算出左右两边的最大值,然后算出当前的最大值,仍然超时,时间复杂度为O(N!),空间复杂度O(1),其中N为气球的个数。与解法一的区别在于,解法一是先戳破当前节点,然后计算当前节点被戳破的情况下,计算剩余节点的情况,而解法二采取的是先把剩余的节点计算出最大值,再戳破当前节点。

 1 import java.util.List;
 2 import java.util.ArrayList;
 3 
 4 public class Solution {
 5     public int maxCoins(int[] nums) {
 6         return maxCoin(nums, 0, nums.length - 1);
 7     }
 8 
 9     public int maxCoin(int[] nums, int left, int right) {
10         if(left > right) return 0;
11 
12         int pre = 0, next = 0;
13         int max = 0;
14         for(int i = left; i <= right; i++) {
15             pre = left == 0 ? 1 : nums[left - 1];
16             next = right == nums.length - 1 ? 1 : nums[right + 1];
17             max = Math.max(max, pre*nums[i]*next + maxCoin(nums, left, i - 1) + maxCoin(nums, i + 1, right));
18         }
19         return max;
20     }
21 }

 

解法三看这里),动态规划,dp[i][j]表示将[i+1, j-1]范围的气球全部戳破可以获得的最大硬币数量。

 1 public class Solution {
 2     public int maxCoins(int[] nums) {
 3         if(nums == null || nums.length == 0) return 0;
 4         int length = nums.length + 2;
 5         int[] arr = new int[length];
 6         arr[0] = 1;
 7         arr[length - 1] = 1;
 8         for(int i = 1; i < length - 1; i++) {
 9             arr[i] = nums[i - 1];
10         }
11         int[][] dp = new int[length][length];
12         for(int len = 2; len < length; len++) {
13             for(int i = 0; i < length - len; i++) {
14                 int j = i + len;
15                 for(int k = i + 1; k < j; k++) {
16                     dp[i][j] = Math.max(dp[i][j], arr[i]*arr[k]*arr[j] + dp[i][k] + dp[k][j]);
17                 }
18             }
19         }
20         return dp[0][length - 1];
21     }
22 }

 

posted @ 2019-11-30 11:19  Latuper  阅读(325)  评论(0编辑  收藏  举报