【算法】——前缀和(矩阵区域和详解,文末附)

简介: 【代码】【算法】——前缀和。

  image.gif 编辑

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

一:前缀和模版

二:前缀和模版2

三:寻找数组的中心下标

四:除自身以外数组的乘积

五:和为K的子数组

六:和被k整除的子数组

七:连续数组

八:矩阵区域和


一:前缀和模版

【模板】前缀和_牛客题霸_牛客网

image.gif 编辑

image.gif 编辑

import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        //1:获取输入
        int n = in.nextInt() , q = in.nextInt();//长度为n的数组,q次查询
        int[] arr = new int[n+1];
        for(int i = 1 ; i <= n ; i++){
            arr[i] = in.nextInt();
        }
        //2:创建dp数组
        long[] dp = new long[n+1]; 
        for(int i = 1 ; i <= n ; i++){
            dp[i] = dp[i-1] + arr[i];
        }
        while(q > 0){
            int l = in.nextInt() , r = in.nextInt();
            System.out.println(dp[r]-dp[l-1]);
            q--;
        }
         
    }
}

image.gif

二:前缀和模版2

【模板】二维前缀和_牛客题霸_牛客网

image.gif 编辑

image.gif 编辑 image.gif 编辑

import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
       int n = in.nextInt() , m = in.nextInt() , q = in.nextInt();
        
        //arr数组
       long[][] arr = new long[n+1][m+1];
       for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++){
            arr[i][j] = in.nextInt();
        }
       }
       //copy创建一个dp数组
       long[][] dp = new long[n+1][m+1];
       for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++){
            dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + arr[i][j];
        }
       }
       while(q > 0){
        int x1 = in.nextInt() , y1 = in.nextInt() , x2 = in.nextInt() , y2 = in.nextInt();
        long result = dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1];
        System.out.println(result);
        q--;
       }
    }
}

image.gif

三:寻找数组的中心下标

724. 寻找数组的中心下标 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

class Solution {
    public int pivotIndex(int[] nums) {
        int n = nums.length;
        //前缀和数组
        int[] f = new int[n];
        f[0] = 0;
        for(int i = 1 ; i < n ; i++){
            f[i] = f[i-1] + nums[i-1];
        }   
        //后缀和数组
        int[] g = new int[n];
        g[n-1] = 0;
        for(int i = n-2 ; i >= 0 ; i--){
            g[i] = g[i+1] + nums[i+1];
        }
        int result = Integer.MAX_VALUE;
        for(int i = 0 ; i < n ; i++){
            if(f[i] == g[i]){
                result = Math.min(result,i);
            }
        }
        if(result == Integer.MAX_VALUE){
            return -1;
        }else{
            return result;
        }
    }
}

image.gif

四:除自身以外数组的乘积

238. 除自身以外数组的乘积 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        //前缀积
        int[] f = new int[n];
        f[0] = 1;
        for(int i=1 ; i<n ; i++ ){
            f[i] = f[i-1]*nums[i-1];
        }
        int[] g = new int[n];
        g[n-1] = 1;
        for(int i=n-2 ; i >= 0 ; i--){
            g[i] = g[i+1]*nums[i+1];
        }
        int[] answer = new int[n];
        for(int i = 0 ; i < n ; i++){
            answer[i] = f[i]*g[i];
        }
        return answer;
    }
}

image.gif

五:和为K的子数组

560. 和为 K 的子数组 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer,Integer> hash = new HashMap<>();
        hash.put(0,1);
        int sum = 0 , ret = 0;
        for(int x : nums){
            sum += x;
            ret += hash.getOrDefault(sum-k,0);
            hash.put(sum,hash.getOrDefault(sum,0)+1);
        }
        return ret;
        
    }
}

image.gif

六:和被k整除的子数组

974. 和可被 K 整除的子数组 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

class Solution {
    public int subarraysDivByK(int[] nums, int k) {
        Map<Integer,Integer> hashMap = new HashMap<Integer,Integer>(); 
        hashMap.put(0 % k , 1);//默认有一个前缀和=0
        int sum = 0;//前缀和
        int ret = 0;//用来计数
        for(int x : nums){
            sum += x;
            int remainder = (sum % k + k) % k;
            ret += hashMap.getOrDefault(remainder,0);
            hashMap.put(remainder,hashMap.getOrDefault(remainder,0)+1);
        }
        
        return ret;
    }
}

image.gif

七:连续数组

525. 连续数组 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

class Solution {
    public int findMaxLength(int[] nums) {
        
        for(int i = 0 ; i < nums.length ; i++){
            if(nums[i] == 0){
                nums[i] = -1;
            }
        }
        Map<Integer,Integer> hash = new HashMap<>();
        hash.put(0,-1);
        int sum = 0 , ret = 0;
        for(int i = 0 ; i < nums.length ; i++){
            sum += nums[i];
            if(hash.containsKey(sum)){
                int old = hash.get(sum);
                int tem = i-old;
                ret = Math.max(ret,tem);
            }else{
                hash.put(sum,i);
            }
        }
        return ret;
    }
}

image.gif

八:矩阵区域和

1314. 矩阵区域和 - 力扣(LeetCode)

image.gif 编辑

image.gif 编辑

image.gif 编辑

class Solution {
    public int[][] matrixBlockSum(int[][] mat, int k) {
        int m = mat.length , n = mat[0].length;
        //1:初始化dp前缀和数组
        int[][] dp = new int[m+1][n+1];
        for(int i = 1 ; i < m+1 ; i++){
            for(int j = 1 ; j < n+1 ; j++){
                dp[i][j] = dp[i-1][j] + dp[i][j-1] -dp[i-1][j-1] + mat[i-1][j-1];
            }
        }
        //2:处理前缀和数组
        int[][] ret = new int[m][n];
        for(int i = 0 ; i < m ; i++){
            for(int j = 0 ; j < n ; j++){
                int x1 = Math.max(0,i-k)+1 , y1 = Math.max(0,j-k)+1;
                int x2 = Math.min(i+k,m-1)+1 , y2 = Math.min(j+k,n-1)+1;
                ret[i][j] = dp[x2][y2] - dp[x2][y1-1] -dp[x1-1][y2] + dp[x1-1][y1-1];
            }
        }
        return ret;
    
    }
}

image.gif


相关文章
|
5月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
5月前
|
算法
【算法】前缀和——前缀和
【算法】前缀和——前缀和
|
3月前
|
并行计算 算法 IDE
【灵码助力Cuda算法分析】分析共享内存的矩阵乘法优化
本文介绍了如何利用通义灵码在Visual Studio 2022中对基于CUDA的共享内存矩阵乘法优化代码进行深入分析。文章从整体程序结构入手,逐步深入到线程调度、矩阵分块、循环展开等关键细节,最后通过带入具体值的方式进一步解析复杂循环逻辑,展示了通义灵码在辅助理解和优化CUDA编程中的强大功能。
|
3月前
|
机器学习/深度学习 算法 搜索推荐
django调用矩阵分解推荐算法模型做推荐系统
django调用矩阵分解推荐算法模型做推荐系统
50 4
|
4月前
|
存储 算法 Java
前缀和算法
本文介绍了前缀和及其变种在解决区间求和问题中的应用。首先,一维前缀和可通过预处理数组快速求得任意区间的和。接着,二维前缀和扩展了这一思想,适用于矩阵操作。此外,文章探讨了如何利用前缀和解决诸如“寻找数组中心下标”、“除自身以外数组的乘积”等问题,并进一步讲解了涉及哈希表优化的“和为 K 的子数组”等相关题目。最后,通过实例展示了如何在矩阵中高效计算特定区域的元素之和。文中包含代码示例与图解说明,便于理解。
56 0
前缀和算法
|
3月前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
212 0
|
3月前
|
人工智能 算法 C++
一篇带你速通前缀和算法(C/C++)
一篇带你速通前缀和算法(C/C++)
|
6月前
|
人工智能 算法 JavaScript
【算法】前缀和与差分
算法学习——前缀和与差分(含一维和二维)
63 4
【算法】前缀和与差分
|
5月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
63 6
|
5月前
|
算法 C++
【算法】前缀和算法——和可被K整除的子数组
【算法】前缀和算法——和可被K整除的子数组