博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
leetcode 312. Burst Balloons
阅读量:6256 次
发布时间:2019-06-22

本文共 2058 字,大约阅读时间需要 6 分钟。

题目要求

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.Find the maximum coins you can collect by bursting the balloons wisely.Note: (1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100Example:Given [3, 1, 5, 8]Return 167nums = [3,1,5,8] --> [3,5,8] -->   [3,8]   -->  [8]  --> []coins =  3*1*5      +  3*5*8    +  1*3*8      + 1*8*1   = 167

这里讲了一个炸气球小游戏的规则。当我们选中一个气球并炸掉它后,会得到该气球以及其相邻两个气球的分数的乘积,并加入我们的积分。之后该气球将消失,从而其左右两个气球成为相邻的气球。问如何选择气球才能使得积分数最高。

思路和代码

我直接解释一下看到的最高票的回答。

如果采用暴力法的话,我们会遍历出所有可能的结果,并且比较其最终获得最高积分值。这意味着O(n!)的时间复杂度。

如果采用动态规划法的话,我们在知道了炸掉k个气球之后的最大积分,然后计算炸掉k+1个气球的最大积分。时间依旧感人。

这里采用的是backtracking+分治法来解决。当我们正向思考这道题时,我们可能会想,随机选择一个气球,按该气球作为分界线分为两个子气球队列。这时再分别计算左右两个队列可以得到的最大积分。

但是这里有一个问题在于,左边队列炸掉气球的顺序可能会影响到右边气球的顺序,比如假设存在这样一列气球对应的积分为3,2,4,1,5,我们取4作为分界点,分为两个子数组3,2,1,5那么如果左边气球炸掉的顺序为2,3,则右边队列的最左侧值则会先是2,再是3。这样就违背了分治法将问题分解为独立问题的要求。因此这种思路无法解决该问题。

但是如果反过来思考,假设我们先选取最后一个炸掉的气球,那么我们知道这个获得的积分一定是nums[i]*nums[left]*nums[right],则以该气球作为分界点将队列分解后获得的两个子队列的边界是一定的。举个例子3,2,4,1,5

首先,我们将其填充为1,3,2,4,1,5,1
然后我们将队列从2分解开来,即2是最后一个炸掉的气球,那么该气球的积分数为1*2*1
自队列分别为1,3,22,4,1,5,1
那么假设我们再拆解1,3,2中的3,则结果为1*3*2。此时得到的子队列长度等于2,因此将无法拆解,即结束。

public int maxCoins(int[] nums) {        int[] modifiedNums = new int[nums.length + 2];        int n = 1;        for(int num : nums){modifiedNums[n++] = num;}        modifiedNums[0] = modifiedNums[n++] = 1;                int[][] memo = new int[n][n];        return maxCoins(modifiedNums, 0, n-1, memo);    }        public int maxCoins(int[] nums, int left, int right, int[][] memo){        if(left+1 >=right) return 0;        if(memo[left][right] != 0) return memo[left][right];        int res = 0;        for(int i = left+1; i

clipboard.png

想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~

转载地址:http://jqnsa.baihongyu.com/

你可能感兴趣的文章
在 Linux 下搭建 Git 服务器
查看>>
StackExchange.Redis Client(转载)
查看>>
Leetcode题目:Bulls and Cows
查看>>
bk. 2014.12.1
查看>>
CEOI2014 wall Spoiler
查看>>
UVA10391 ZOJ1825 Compound Words【SET+暴力】
查看>>
动态规划------Combination Sum IV
查看>>
[BZOJ2463][中山市选2009]谁能赢呢?
查看>>
iOS数据持久化存储之属性列表
查看>>
最后冲刺时间
查看>>
前端开发薪资之各地区对比(图文分析)
查看>>
jquery简单的大背景banner图片全屏切换
查看>>
java疑问
查看>>
JAVAEE 介绍
查看>>
视图和路由
查看>>
优酷新版播放器站外调用代码详解
查看>>
Python之操作符优先级
查看>>
【学习笔记】PHP会话控制
查看>>
面试题 17:合并两个排序的链表
查看>>
Linux命令--链接文件的那些事
查看>>