一、二维前缀和算法

文章目录

  • 前缀和模板
  • 724. 寻找数组的中心下标
  • 238. 除自身以外数组的乘积
  • 560. 和为 K 的子数组
  • 974. 和可被 K 整除的子数组
  • 525. 连续数组
  • 1314. 矩阵区域和

前缀和模板

一维前缀和:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(),q = scan.nextInt();
        int[] arr = new int[n + 1];
        long[] dp = new long[n + 1];
        for(int i = 1;i <= n;i++) {
            arr[i] = scan.nextInt();
            dp[i] = dp[i - 1] + arr[i];
        }
        while(q > 0) {
            int l = scan.nextInt(),r = scan.nextInt();
            System.out.println(dp[r] - dp[l - 1]);
            q--;
        }
    }
}

二维前缀和:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(),m = scan.nextInt(),q = scan.nextInt();
        int[][] arr = new int[n + 1][m + 1];
        long[][] dp = new long[n + 1][m + 1];
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= m;j++) {
                arr[i][j] = scan.nextInt();
                dp[i][j] = arr[i][j] + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];
            }
        }
        while(q > 0) {
            int x1 = scan.nextInt(),y1 = scan.nextInt();
            int x2 = scan.nextInt(),y2 = scan.nextInt();
            System.out.println(dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]);
            q--;
        }
    }
}

724. 寻找数组的中心下标

给你一个整数数组 nums ,请计算数组的 中心下标

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。
一、二维前缀和算法_第1张图片

class Solution {
    public int pivotIndex(int[] nums) {
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];

        for(int i = 1;i < n;i ++) {
            f[i] = f[i - 1] + nums[i - 1];
        }
        for(int j = n - 2;j >= 0;j--) {
            g[j] = g[j + 1] + nums[j + 1];
        }
        for(int i = 0;i < n;i++) {
            if(f[i] == g[i]) {
                return i;
            }
        }
        return -1;
    }
}

238. 除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请不要使用除法,且在 O(n) 时间复杂度内完成此题。
一、二维前缀和算法_第2张图片

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

560. 和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。
一、二维前缀和算法_第3张图片

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;
    }
}

974. 和可被 K 整除的子数组

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。
一、二维前缀和算法_第4张图片

class Solution {
    public int subarraysDivByK(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;
            int r = (sum % k + k) % k;
            ret += hash.getOrDefault(r,0);
            hash.put(r,hash.getOrDefault(r,0) + 1);
        }
        return ret;
    }
}

525. 连续数组

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
一、二维前缀和算法_第5张图片

class Solution {
    public int findMaxLength(int[] nums) {
        Map<Integer,Integer> hash = new HashMap<>();
        hash.put(0,-1); //默认存在一个前缀和为0的情况

        int sum = 0,ret = 0;
        for(int i = 0; i < nums.length;i++) {
            sum += (nums[i] == 0 ? -1 : 1);
            if(hash.containsKey(sum)) {
                ret = Math.max(ret,i - hash.get(sum));
            } else {
                hash.put(sum,i);
            }
        }
        return ret;
    }
}

1314. 矩阵区域和

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

i - k <= r <= i + k, j - k <= c <= j + k 且(r, c) 在矩阵内。
一、二维前缀和算法_第6张图片

class Solution {
    public int[][] matrixBlockSum(int[][] mat, int k) {
        int m = mat.length,n = mat[0].length;

        int[][] dp = new int[m + 1][n + 1];
        for(int i = 1;i <= m;i++) {
            for(int j = 1;j <= n;j++) {
                dp[i][j] = mat[i - 1][j - 1] + dp[i - 1][j] + dp[i][j - 1] 
                - dp[i - 1][j - 1];
            }
        }
        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;
                int y1 = Math.max(0,j - k) + 1;
                int x2 = Math.min(m - 1,i + k) + 1;
                int y2 = Math.min(n - 1,j + k) + 1;
                ret[i][j] = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1-1][y1-1];
            }
        }
        return ret;
    }
}

你可能感兴趣的:(数据结构与算法,算法,java,开发语言)