Java前缀和(洛谷P8772 )

本文介绍了前缀和的概念,其在计算子数组和上的优势,以及如何通过Java实现前缀和的计算。还探讨了前缀和的哈希优化方法,并以蓝桥杯题目为例,展示了前缀和在解决两两相乘再相加和的问题中的应用。
摘要由CSDN通过智能技术生成

前缀和(Prefix Sum)

前缀和的详细解释

  • 前缀和:前缀和是一种数组处理技巧,用于快速计算数组中某一段连续子数组的和。它通过将数组中每个位置的值依次累加,得到一个新的数组,这个新数组的第i个元素就是原数组前i个元素的和。
  • 前缀和数组:前缀和数组是一个与原数组长度相同的数组,其中第i个元素存储了原数组从索引0到索引i的所有元素的和。

前缀和有什么用

  • 快速计算子数组和:通过前缀和数组,可以在O(1)的时间复杂度内计算任意子数组的和,而不需要每次都重新遍历计算。
  • 解决一些子数组和的问题:前缀和可以用于解决一些子数组和相关的问题,如最大子数组和、连续子数组和等。

前缀和的示例Java代码

下面是一个简单的Java代码示例,演示如何计算数组的前缀和:

public class PrefixSum {
    // 计算数组的前缀和
    public static int[] calculatePrefixSum(int[] nums) {
        int n = nums.length;
        int[] prefixSum = new int[n];
        
        prefixSum[0] = nums[0];
        for (int i = 1; i < n; i++) {
            prefixSum[i] = prefixSum[i - 1] + nums[i];
        }
        
        return prefixSum;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4, 5};
        
        // 计算前缀和数组
        int[] prefixSum = calculatePrefixSum(nums);
        
        // 输出前缀和数组
        for (int num : prefixSum) {
            System.out.print(num + " ");
        }
    }
}

进阶前缀和哈希等

  • 前缀和的哈希优化:对于一些问题,我们可能需要求解子数组和等相关问题时,通过哈希表优化前缀和的计算,可以进一步提高效率。
  • 前缀和的应用:前缀和不仅可以用于求解子数组和等问题,还可以应用于解决一些其他的问题,如区间和查询、区间更新等。

例题

P8772 [蓝桥杯 2022 省 A] 求和

解题教程:利用前缀和求解两两相乘再相加的和
理解题目

题目要求给定n个整数,求它们两两相乘再相加的和。具体地,对于给定的n个整数a1, a2, …, an,需要计算以下形式的和:

S = a 1 ⋅ a 2 + a 1 ⋅ a 3 + ⋯ + a 1 ⋅ a n + a 2 ⋅ a 3 + ⋯ + a n − 2 ⋅ a n − 1 + a n − 2 ⋅ a n + a n − 1 ⋅ a n S = a_{1} \cdot a_{2} + a_{1} \cdot a_{3} + \cdots + a_{1} \cdot a_{n} + a_{2} \cdot a_{3} + \cdots + a_{n-2} \cdot a_{n-1} + a_{n-2} \cdot a_{n} + a_{n-1} \cdot a_{n} S=a1a2+a1a3++a1an+a2a3++an2an1+an2an+an1an

解法一

我们可以利用前缀和来解决这个问题。具体步骤如下:

  • 计算数组的前缀和数组prefixSum[],其中prefixSum[i]表示前i个元素的和。
  • 对于每个数a[i],它与a[0]相乘的结果在前缀和数组中的位置为i+1,它与a[1]相乘的结果在前缀和数组中的位置为i+2,以此类推。
  • 遍历数组,对于每个数a[i],将其与a[i+1]到a[n-1]的前缀和相乘,累加到结果中。
Java代码实现

下面是使用Java实现的代码:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取数组大小
        int n = scanner.nextInt();
        // 读取数组元素
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = scanner.nextInt();
        }
        // 计算前缀和数组
        long[] prefixSum = new long[n + 1];
        prefixSum[0] = 0;
        for (int i = 1; i <= n; i++) {
            prefixSum[i] = prefixSum[i - 1] + nums[i - 1];
        }
        // 计算结果
        long sum = 0;
        for (int i = 0; i < n; i++) {
            sum += nums[i] * (prefixSum[n] - prefixSum[i]);
        }
        // 输出结果
        System.out.println(sum);
        scanner.close();
    }
}
时间复杂度分析
  • 计算前缀和数组的时间复杂度为O(n),遍历数组计算结果的时间复杂度为O(n),因此总的时间复杂度为O(n)。
  • 空间复杂度为O(n),主要用于存储前缀和数组。
解法二

"后缀和“

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int arr[] = new int[n];
        long sumarr[] = new long[n]; 
        long sum = 0;
        for (int i = 0 ;i < n;i++) {
        	 arr[i] = scanner.nextInt();
        }
        for(int i = n-1; i>0; i--) {
        	if(i == n-1) sumarr[i] = arr[i];
        	else sumarr[i] = sumarr[i+1] + arr[i];
        }
        for(int i = 0; i < n-1; i ++) {

        	sum += arr[i] * sumarr[i+1];

        }
        System.out.println(sum);


        scanner.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BenChuat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值