一.题目描述
NC564牛牛打怪兽
现在牛牛面前有n只怪兽,第i只怪兽的血量为ai。牛牛可以使用这个组合拳打第X怪兽,同时会打到第2X、2X+1这两个怪兽,每次组合拳会扣打到的怪兽一滴血。一个怪兽血量为0即为死亡,同时组合拳是可以鞭尸的,这意味着即使怪兽死亡,也可以对其使用组合拳。值得注意的是组合拳必须攻击三只怪兽。牛牛想知道它需要使用最少多少次组合拳才能把所有怪兽打死,如果打不死请输出-1。
二.算法(模拟)
首先我们要意识到组合拳是一次性可以打三只怪兽,并且打第X怪兽的时候,同时会打到第2X、2X+1这两个怪兽,每次组合拳会扣打到的怪兽一滴血,也就是说只有怪兽的数目是奇数的时候(而且数量大于2)才可以把所有怪兽打死,对于可以打死所有怪兽的情况,我们只需要利用数组进行模拟就行了,下面是完整代码:
class Solution { public: int slove(int n, vector<int>& A) { //特判断 无法将所有的怪兽消灭的怪兽数目 if(n<=2||(n%2==0)){ return -1; } //记录需要打的组合数数目 int ans=0; for(int i=n/2-1;i>=0;i--){ //下标是从0开始的 所以是2*i+1和2*i+2 int a=max(A[2*i+2],A[2*i+1]); //要是怪兽已经死了 直接为0 A[i]=max(A[i]-a,0); ans+=a; } //这块要注意最后一个怪兽要对其施加A[0]次组合拳 return ans+A[0]; } };
时间复杂度: 只需要对数组进行一次遍历
空间复杂度: 不需要额外空间
优缺点:时间复杂度低,代码简单便于实现。
三.算法(利用java实现)
利用java同样可以实现下面是完整代码:
import java.util.*; public class Solution { public int slove (int n, int[] A) { //特判断 无法将所有的怪兽消灭的怪兽数目 if(n<=2||(n%2==0)){ return -1; } //记录需要打的组合数数目 int ans=0; for(int i=n/2-1;i>=0;i--){ //下标是从0开始的 所以是2*i+1和2*i+2 //利用Math类判断大小 int a=Math.max(A[2*i+2],A[2*i+1]); //要是怪兽已经死了 直接为0 A[i]=Math.max(A[i]-a,0); ans+=a; } //这块要注意最后一个怪兽要对其施加A[0]次组合拳 return ans+A[0]; } }
时间复杂度: 只需要对数组的一半进行一次遍历
空间复杂度: 不需要额外空间来存储数据
优缺点:时间复杂度低,代码简单和c++一样便于实现。