C语言/数据结构贡献法题解:数组权值——所有连续子数组中不同数字个数之和(O(n)解法)

问题描述

小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拿到了一个数组,他想请你帮忙计算这个数组的权值是多少。注意:数组可能包含重复元素,你需要高效地计算总权值。

要求:

  1. 设计一个算法,时间复杂度为 O(n),其中 n 是数组的长度。
  2. 尽量减少额外空间的使用,以体现你的算法优化能力。

测试样例

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

运行结果

相关推荐
机器人零零壹17 小时前
技术白皮书:iRobotCAM如何解决机器人激光切割应用中的核心难点,从CAD离线编程到双目视觉定位与轨迹自适应提升复杂空间曲线切割的精度、效率与柔性化水平
人工智能·算法
布莱克60518 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
ZhengEnCi20 小时前
大模型的分类到底怎么分:从基础模型到推理模型、从通用到专用的完整图谱
算法
取名真是21 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
罗西的思考21 小时前
【轻量化复刻大模型 / KIMI K3】KDA 模块交互式演示
人工智能·算法·机器学习
揽星河..1 天前
【C语言】底层程序设计
c语言·开发语言
nm_zfyjt1 天前
信息流广告投放优化实践:线索成本评估模型与转化链路重构(家装建材案例)
算法·重构·内蒙古朋友圈广告服务商·内蒙古朋友圈获客
w_zero_one1 天前
算法--构造
java·数据结构·算法
其实防守也摸鱼1 天前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php