
2026-02-26:锯齿形数组的总数Ⅰ。用go语言,给定三个整数 n、l、r,要求构造长度为 n 的数组,元素取自区间 [l, r],并满足以下两条规则:
求满足上述条件的数组数量,并将结果对 1000000007 取模后返回。
说明:
3 <= n <= 2000。
1 <= l < r <= 2000。
输入:n = 3, l = 4, r = 5。
输出:2。
解释:
在取值范围 [4, 5] 内,长度为 n = 3 的锯齿形数组只有 2 种:
[4, 5, 4] [5, 4, 5]
题目来自力扣3699。
首先明确题目规则的本质:
以输入 n=3, l=4, r=5 为例,取值范围只有4、5两个数,符合条件的只有 [4,5,4](模式1)和 [5,4,5](模式2),总数为2,与输出一致。
mod = 1e9+7:用于结果取模,避免数值溢出;k = r - l + 1:计算取值范围的元素个数,本例中 k=5-4+1=2;f := make([]int, k):创建长度为k的动态规划(DP)数组,f[j] 表示“以第j个数值(对应区间[l, r]中的l+j)结尾的、满足条件的数组数量”;f 所有元素为1:因为数组长度为1时(i=0),每个数值都可以作为起始元素,数量为1。本例中 f = [1, 1](对应数值4、5)。循环变量 i 表示“当前构造到数组的第i个位置”(数组索引从0开始),i%2 控制当前位置的增减规则:
i%2 > 0(i为奇数,对应数组第2个位置):要求当前位置比前一个位置大(对应模式1的上升段);i%2 == 0(i为偶数,对应数组第3个位置):要求当前位置比前一个位置小(对应模式1的下降段)。i=1 是奇数,执行“增”的逻辑:
pre 记录“比当前数值小的所有数值的数量之和”(因为要满足前小后大);f 数组(j=0到1):f[0] = pre = 0,pre += 原f[0] = 1(pre变为1);f[1] = pre = 1,pre += 原f[1] = 1(pre变为2);f = [0, 1]:表示数组长度为2时,以4结尾的有效数组数为0(没有数比4小且不相等),以5结尾的有效数组数为1(只有[4,5])。i=2 是偶数,执行“减”的逻辑:
suf 记录“比当前数值大的所有数值的数量之和”(因为要满足前大后小);f 数组(j=1到0):f[1] = suf = 0,suf += 原f[1] = 1(suf变为1);f[0] = suf = 1,suf += 原f[0] = 0(suf仍为1);f = [1, 0]:表示数组长度为3时,以4结尾的有效数组数为1(即[4,5,4]),以5结尾的有效数组数为0。f 数组所有元素:ans = 1 + 0 = 1(这是模式1的总数);1×2=2;f:长度为k,空间复杂度O(k);f记录“以每个数值结尾的有效数组数”,按奇偶位置交替执行“增/减”逻辑更新DP数组,最后累加单模式总数并乘以2得到最终结果;.
package main
import (
"fmt"
)
func zigZagArrays(n, l, r int) (ans int) {
const mod = 1_000_000_007
k := r - l + 1
f := make([]int, k)
for i := range f {
f[i] = 1
}
for i := 1; i < n; i++ {
if i%2 > 0 { // 增
pre := 0
for j, v := range f {
f[j] = pre % mod
pre += v
}
} else { // 减
suf := 0
for j := k - 1; j >= 0; j-- {
v := f[j]
f[j] = suf % mod
suf += v
}
}
}
for _, v := range f {
ans += v
}
return ans * 2 % mod
}
func main() {
n := 3
l := 4
r := 5
result := zigZagArrays(n, l, r)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
def zigZagArrays(n, l, r):
mod = 1_000_000_007
k = r - l + 1
# f[j] 表示以值 l+j 结尾的当前长度的序列个数
f = [1] * k
for i in range(1, n):
if i % 2 == 1: # 奇数索引,需要上升
pre = 0
for j in range(k):
# 对于位置 j,前面所有更小的数都可以接在它前面
# 因为当前长度需要上升,所以结尾数字 j 前面必须小于 j
pre_val = pre
pre = (pre + f[j]) % mod
f[j] = pre_val
else: # 偶数索引,需要下降
suf = 0
for j in range(k-1, -1, -1):
# 对于位置 j,后面所有更大的数都可以接在它前面
# 因为当前长度需要下降,所以结尾数字 j 前面必须大于 j
suf_val = suf
suf = (suf + f[j]) % mod
f[j] = suf_val
# 求和所有可能的结尾值
ans = sum(f) % mod
# 乘以2的原因:题目可能要求两种方向(先增后减或先减后增)
# 但这里已经处理了奇偶的情况,可能需要根据实际题目调整
return (ans * 2) % mod
def main():
n = 3
l = 4
r = 5
result = zigZagArrays(n, l, r)
print(result)
if __name__ == "__main__":
main()
.
#include <iostream>
#include <vector>
using namespace std;
constint MOD = 1000000007;
long long zigZagArrays(int n, int l, int r) {
int k = r - l + 1;
// f[j] 表示以值 l+j 结尾的当前长度的序列个数
vector<long long> f(k, 1);
for (int i = 1; i < n; i++) {
if (i % 2 == 1) { // 奇数索引,需要上升
long long pre = 0;
for (int j = 0; j < k; j++) {
long long v = f[j];
f[j] = pre % MOD;
pre = (pre + v) % MOD;
}
} else { // 偶数索引,需要下降
long long suf = 0;
for (int j = k - 1; j >= 0; j--) {
long long v = f[j];
f[j] = suf % MOD;
suf = (suf + v) % MOD;
}
}
}
// 求和所有可能的结尾值
long long ans = 0;
for (int j = 0; j < k; j++) {
ans = (ans + f[j]) % MOD;
}
// 乘以2的原因:题目可能要求两种方向(先增后减或先减后增)
// 但这里已经处理了奇偶的情况,可能需要根据实际题目调整
return (ans * 2) % MOD;
}
int main() {
int n = 3;
int l = 4;
int r = 5;
long long result = zigZagArrays(n, l, r);
cout << result << endl;
return0;
}

·
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。
·