前缀和算法例题

前缀和(preSum)是一种常用的、较为高效的预处理方式,相比于暴力解法,能够有效减低查询的时间复杂度。

题目

有n个战士站成一排,分别编号为1、2、3、...、n,战士的战斗力等于他的编号,有一些战士只会进攻,有一些战士只会防守。

现在我们要将他们从某个点开始分成两个阵营,假设这个点为pos(0<=pos<=n),则编号为1、2、3、...、pos的战士为第一个阵营, pos+1、pos+2、...、n的战士为第二个阵营。假设pos为0时, 说明第一阵营没有战士,所有战土都在第二阵营。

我们令第一个阵营为进攻方,第二个阵营为防守方,假设第一个阵营中能够进攻的战士战斗力总和为w,第二个阵营中能够防守的战士战斗力总和为v,我们希望|w-v|的值最小,其中||为绝对值符号,求|w-v|最小值。

输入

第一行输入一个正整数n,表示战士的数量(1<=n)。

第二行给出一个字符串s,仅由字符0或1组成,字符串中的每一位分别代表每一位的战士属性,0代表这个战士只会进攻,1代表这个战士只会防守。

输出

输出一行一个整数表示|w-v|最小值。

示例

输入

4

0011

输出

1

思路

前缀和

使用一个数组L[n],来统计左边的攻击力,另一个数组R[n],来统计右边的防御力。

然后在一个循环中找出|w-v|最小值。

代码

public class TestDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        if(n==1){
            System.out.println(0);
        }
        String s = sc.next();
        int[] L = new int[n];
        int[] R = new int[n];
        int countL = 0;
        int countR = 0;
        for(int i=0;i<n;++i){
            if(s.charAt(i)=='0'){
                countL+=i+1;
            }
            L[i] = countL;
        }
        for(int i=n-1;i>0;--i){
            if(s.charAt(i)=='1'){
                countR+=i+1;
            }
            R[i] = countR;
        }
        int min = Integer.MAX_VALUE;
        for(int i=0;i<n-1;++i){
            int fight =Math.abs(L[i]-R[i+1]);
            min=Math.min(min,fight);
        }
        min=Math.min(min,Math.min(R[n-1],L[n-1]));
        System.out.println(min);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值