移动射击--算法笔试模拟题精解

题目描述

你正在数轴上跟小精灵对战。你拥有一个十分强力的技能称为移动射击,但是这
个技能有一个缺点是在你发动之后只能改变一次方向。
你可以认为你的位置在数字 0 的位置上,在数轴的正方向上有 n 只精灵,负方向
上有 m 只精灵。移动射击可以造成 w 点伤害。每个精灵都有自己的血量,当血量降
为 0 时死亡。
在最开始时你可以选择向正方向或负方向释放移动射击,并且可以在任意时刻改
变技能的方向。请问你最多可以击杀多少只小精灵 ?(n,m,w 以及精灵的血量均在
[1, 100000] 范围内 )
输入内容为五个,前三个为三个数字 :正方向上的精灵个数 n、负方向上的精灵
个数 m, 移动射击可以造成的伤害 w;第四个是一个长度为 n 的数组 a,表示正方向
上的 n 个精灵的血量;第五个是一个长度为 m 的数组 b,表示负方向上的 m 个精灵
的血量。
输出一个数字,表示最多能够击杀的精灵数量。

示例 1

输入:
3
4
10
[1, 2, 3]
[4, 3, 2 ,1]
输出:
4

解题思路

大致思路: 首先理解题意,题目说的“发动之后只能改变一次方向”是干扰你
的,因为即使你在中间过程中左右摆,但宏观上还是最多改变了一次方向。
如果说:我先杀左边一个,然后转头杀右边一个,再转头杀左边三个,又回头杀
右边 1 个,看起来是不是改变了三次方向,其实呢,相当于我先杀左边四个,再回头
杀右边两个,效果是一样的。因为你想这个问题的时候,可以忽略这个限制。
具体过程: 先遍历数组 a,a[i] 表示数组 a 前 i 个数的和,当 a[i]>=w 的时候,记
住此时的位置 index_a=i,退出循环,退出后加上这句 if(i==n||a[i]>w) index_a–;
因为 index_a 指向的是刚好不超过 w 的位置,而且不能越界。
对 b 数组也是如此,然后开始从 index_a 往后一步一步走 ;
走一步,看看 b 数组的情况,k 为 b 数组的下标,初始 k=0;

while(k<m &&a[i]+b[k]<=w) k++;

然后和当前最长的长度比较

ans=Math.max(ans,i+k+1);

当 index_a 一直走到底,可返回 ans.

参考代码

public class Solution075 {

    /**
     * 移动射击
     * @param n 正方向上的精灵个数 n
     * @param m 负方向上的精灵个数 m
     * @param w 移动射击可以造成的伤害 w
     * @param a 一个长度为 n 的数组 a,表示正方向 上的 n 个精灵的血量
     * @param b 一个长度为 m 的数组 b,表示负方向上的 m 个精灵的血量
     * @return
     */
    public static int solution(int n, int m, int w, int[] a, int[] b) {
        int index_a = 0;
        int index_b = 0;
        int sum_a = 0;
        int sum_b = 0;
        for(int i = 0;i<a.length;i++){
            sum_a = sum_a + a[i];
            index_a = i;
            if( sum_a > w){
                index_a = i - 1;
                sum_a = sum_a - a[i];
                break;
            }
        }
        int ans1 = 0;
        for(int ina = index_a;ina >= 0;sum_a = sum_a - a[ina],ina--){
            int k = 0;
            int sum = sum_a;
            while(k<m && sum+b[k]<=w){
                sum = sum +b[k];
                k++;
            }
            ans1 = Math.max(ans1,ina+k+1);
        }
        for(int i = 0;i<b.length;i++){
            sum_b = sum_b + b[i];
            index_b = i;
            if(sum_b > w){
                index_b = i - 1;
                sum_b = sum_b - b[i];
                break;
            }
        }
        int ans2 = 0;
        for(int inb = index_b;inb >= 0;sum_b = sum_b - b[inb],inb--){
            int k = 0;
            int sum = sum_b;
            while(k<n && sum+a[k]<=w){
                sum = sum +a[k];
                k++;
            }
            ans2 = Math.max(ans2,inb+k+1);
        }
        int ans = 0;
        ans =  Math.max(ans1,ans2);
        return ans;
    }

    public static void main(String[] args){
        int[] a = {4,3,2,1};
        int[] b = {1,2,3};
        System.out.println(solution(4,3,10,a,b));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值