问题描述
小A最近在研究数组的权值问题。他发现一个数组的权值定义为:所有连续子数组中,不同数字的个数之和。例如,数组 1,2,1 的连续子数组有 1, 2, 1, 1,2, 2,1, 1,2,1,它们的权值分别是 1,1,1,2,2,2,总和为 1+1+1+2+2+2=9。
现在小A拿到了一个数组,他想请你帮忙计算这个数组的权值是多少。注意:数组可能包含重复元素,你需要高效地计算总权值。
要求:
- 设计一个算法,时间复杂度为 O(n),其中 n 是数组的长度。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
测试样例
样例1:
输入:
nums = [1,2,1]输出:9解释:所有连续子数组为 1 (权值1), 2 (权值1), 1 (权值1), 1,2 (权值2), 2,1 (权值2), 1,2,1 (权值2),总和为 1+1+1+2+2+2=9。
样例2:
输入:
nums = [1,1,1]输出:6解释:连续子数组有 1 (权值1), 1 (权值1), 1 (权值1), 1,1 (权值1), 1,1 (权值1), 1,1,1 (权值1),总和为 1+1+1+1+1+1=6。
样例3:
输入:
nums = [1,2,3]输出:10解释:连续子数组为 1 (1), 2 (1), 3 (1), 1,2 (2), 2,3 (2), 1,2,3 (3),总和为 1+1+1+2+2+3=10。
约束条件
- 1 ≤ nums.length ≤ 1000
- 1 ≤ numsi ≤ 1000
- 数组长度 n 满足 1 ≤ n ≤ 1000
程序代码
#include <stdio.h>
#include <string.h>
int arrayWeight(int* nums, int numsSize) {
// lastPosvalue 记录每个值最近一次出现的位置
int lastPos1001;
for (int i = 0; i <= 1000; i++) {
lastPosi = -1;
}
int total = 0;
for (int i = 0; i < numsSize; i++) {
int val = numsi;
int prev = lastPosval;
// numsi 贡献的子数组数量
total += (i - prev) * (numsSize - i);
// 更新最近位置
lastPosval = i;
}
return total;
}
int main() {
int nums1\[\] = {1, 2, 1};
int nums2\[\] = {1, 1, 1};
int nums3\[\] = {1, 2, 3};
printf("%d\n", arrayWeight(nums1, 3)); // 9
printf("%d\n", arrayWeight(nums2, 3)); // 6
printf("%d\n", arrayWeight(nums3, 3)); // 10
return 0;
}
cpp
#include <stdio.h>
#include <string.h>
int arrayWeight(int* nums, int numsSize) {
// lastPos[value] 记录每个值最近一次出现的位置
int lastPos[1001];
for (int i = 0; i <= 1000; i++) {
lastPos[i] = -1;
}
int total = 0;
for (int i = 0; i < numsSize; i++) {
int val = nums[i];
int prev = lastPos[val];
// nums[i] 贡献的子数组数量
total += (i - prev) * (numsSize - i);
// 更新最近位置
lastPos[val] = i;
}
return total;
}
int main() {
int nums1[] = {1, 2, 1};
int nums2[] = {1, 1, 1};
int nums3[] = {1, 2, 3};
printf("%d\n", arrayWeight(nums1, 3)); // 9
printf("%d\n", arrayWeight(nums2, 3)); // 6
printf("%d\n", arrayWeight(nums3, 3)); // 10
return 0;
}
运行结果
