/
Week 6 @ 2025 算法周记【前缀和 + 滑动窗口】
Week 6 @ 2025 算法周记【前缀和 + 滑动窗口】
前缀和
LC 1314. 矩阵区域和
https://leetcode.com/problems/matrix-block-sum/
func matrixBlockSum(mat [][]int, k int) [][]int {
m, n := len(mat), len(mat[0])
sums := getSumsArray(mat)
getI := func(i int) int {
if i <= 0 {
return 0
} else if i >= m-1 {
return m-1
} else {
return i
}
}
getJ := func(j int) int {
if j <= 0 {
return 0
} else if j >= n-1 {
return n-1
} else {
return j
}
}
getRangeSum := func(T, B, L, R int) int {
safe := func(i, j int) int {
if i < 0 || j < 0 {
return 0
}
return sums[i][j]
}
return sums[B][R] - safe(B, L-1) - safe(T-1, R) + safe(T-1, L-1)
}
result := new2dArray(m, n)
for i := 0; i < m; i++ {
T, B := getI(i-k), getI(i+k)
for j := 0; j < n; j++ {
L, R := getJ(j-k), getJ(j+k)
result[i][j] = getRangeSum(T, B, L, R)
}
}
return result
}
func new2dArray(m, n int) [][]int {
arr := make([][]int, m)
for i := range arr {
arr[i] = make([]int, n)
}
return arr
}
func getSumsArray(mat [][]int) [][]int {
m, n := len(mat), len(mat[0])
sums := new2dArray(m, n)
sums[0][0] = mat[0][0]
for j := 1; j < n; j++ {
sums[0][j] = sums[0][j-1] + mat[0][j]
}
for i := 1; i < m; i++ {
sums[i][0] = sums[i-1][0] + mat[i][0]
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
sums[i][j] = sums[i-1][j] + sums[i][j-1] - sums[i-1][j-1] + mat[i][j]
}
}
return sums
}
LC 724. 寻找数组的中心下标
https://leetcode.com/problems/find-pivot-index/description/
func pivotIndex(nums []int) int {
n := len(nums)
leftSum := make([]int, n+1)
for i := range nums {
leftSum[i+1] = leftSum[i] + nums[i]
}
rightSum := make([]int, n+1)
for i := n - 1; i >= 0; i-- {
rightSum[i] = rightSum[i+1] + nums[i]
}
for i := range nums {
if leftSum[i] == rightSum[i+1] {
return i
}
}
return -1
}
只使用前缀和(不计算后缀和)
func pivotIndex(nums []int) int {
n := len(nums)
leftSum := make([]int, n+1)
totalSum := 0
for i, v := range nums {
leftSum[i+1] = leftSum[i] + v
totalSum += v
}
for i, v := range nums {
if leftSum[i] == totalSum - leftSum[i] - v {
return i
}
}
return -1
}
前缀积
LC 238. 除自身以外数组的乘积
https://leetcode.com/problems/product-of-array-except-self/description/
func productExceptSelf(nums []int) []int {
n := len(nums)
preProduct := make([]int, n+1)
preProduct[0] = 1
for i, v := range nums {
preProduct[i+1] = preProduct[i] * v
}
postProduct := make([]int, n+1)
postProduct[n] = 1
for i := n-1; i >= 0; i-- {
postProduct[i] = postProduct[i+1] * nums[i]
}
results := make([]int, n)
for i := range nums {
results[i] = preProduct[i] * postProduct[i+1]
}
return results
}
不使用额外空间
func productExceptSelf(nums []int) []int {
n := len(nums)
result := make([]int, n)
result[0] = 1
v := 1
for i := 1; i < len(nums); i++ {
v *= nums[i-1]
result[i] = v
}
v = 1
for i := len(nums) - 2; i >= 0; i-- {
v *= nums[i+1]
result[i] *= v
}
return result
}
LC 1352. 最后 K 个数的乘积
https://leetcode.com/problems/product-of-the-last-k-numbers/description/
type ProductOfNumbers struct {
products []int
}
func Constructor() ProductOfNumbers {
return ProductOfNumbers{
products: []int{1},
}
}
func (this *ProductOfNumbers) Add(num int) {
if num == 0 {
this.products = []int{1}
return
}
this.products = append(this.products, this.products[len(this.products)-1] * num)
}
func (this *ProductOfNumbers) GetProduct(k int) int {
n := len(this.products)
if n-1 < k {
return 0
}
return this.products[n-1] / this.products[n-k-1]
}
/**
* Your ProductOfNumbers object will be instantiated and called as such:
* obj := Constructor();
* obj.Add(num);
* param_2 := obj.GetProduct(k);
*/
滑动窗口
LC 1658. 将 x 减到 0 的最小操作数
https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/
dfs(超时)
func minOperations(nums []int, x int) int {
v := dfs(nums, x)
if v >= MAX {
return -1
} else {
return v
}
}
func dfs(nums []int, x int) int {
if x == 0 {
return 0
}
if len(nums) == 1 {
if nums[0] == x {
return 1
} else {
return MAX
}
}
v := MAX
if nums[0] <= x {
v = dfs(nums[1:], x-nums[0]) + 1
}
if nums[len(nums)-1] <= x {
v = min(
v,
dfs(nums[:len(nums)-1], x-nums[len(nums)-1]) + 1,
)
}
return v
}
const MAX = 1_000_000_001
dfs + 记忆化数组(OOM)
func minOperations(nums []int, x int) int {
mem := newMatrix(len(nums))
v := dfs(nums, x, 0, len(nums)-1, mem)
if v >= MAX {
return -1
} else {
return v
}
}
func dfs(nums []int, x int, i, j int, mem [][]int) int {
if x == 0 {
return 0
}
if i > j {
return MAX
}
if i == j {
if nums[i] == x {
return 1
} else {
return MAX
}
}
v := MAX
if mem[i][j] != 0 {
return mem[i][j]
}
defer func() {
mem[i][j] = v
}()
if nums[i] <= x {
v = dfs(nums, x-nums[i], i+1, j, mem) + 1
}
if nums[j] <= x {
v = min(
v,
dfs(nums, x-nums[j], i, j-1, mem) + 1,
)
}
return v
}
const MAX = 1_000_000_001
func newMatrix(n int) [][]int {
m := make([][]int, n)
for i := range m {
m[i] = make([]int, n)
}
return m
}
滑动窗口(变换)
func minOperations(nums []int, x int) int {
target := -x
for _, v := range nums {
target += v
}
l := -1
i, j := 0, 0
sum := 0
for j < len(nums) {
sum += nums[j]
j++
for i < j && sum > target {
sum -= nums[i]
i++
}
if sum == target {
l = max(l, j-i)
}
}
if l == -1 {
return -1
} else {
return len(nums) - l
}
}
const MAX = 100_005
LC 713. 乘积小于 K 的子数组
https://leetcode.com/problems/subarray-product-less-than-k/
func numSubarrayProductLessThanK(nums []int, k int) int {
i, j := 0, 0
product := 1
count := 0
for j < len(nums) {
product *= nums[j]
j++
for i < j && product >= k {
product /= nums[i]
i++
}
n := j - i
count += n
}
return count
}
Related content
Week 3 @ 2025 算法周记【前缀和 + 双指针数组】
Week 3 @ 2025 算法周记【前缀和 + 双指针数组】
More like this
Week 2 @ 2025 算法周记【nSum + 双指针数组】
Week 2 @ 2025 算法周记【nSum + 双指针数组】
More like this
Week 51 @ 2024 算法周记【双指针链表+丑数】
Week 51 @ 2024 算法周记【双指针链表+丑数】
More like this
Week 44 @ 2024 算法周记【二分查找】
Week 44 @ 2024 算法周记【二分查找】
More like this
Week 5 @ 2025 算法周记【滑动窗口】
Week 5 @ 2025 算法周记【滑动窗口】
More like this
Week 42 @ 2024 算法周记【双指针数组】
Week 42 @ 2024 算法周记【双指针数组】
More like this