当前位置: 首页 > news >正文

Kimi LeetCode 3739. 统计主要元素子数组数目 II C语言实现

以下是 LeetCode 3739. 统计主要元素子数组数目 II 的 C 语言实现。

题目分析

这道题要求统计数组 `nums` 中满足 `target` 是主要元素(出现次数严格大于子数组长度的一半)的子数组数目。

核心思路:
1. 将数组中等于 `target` 的元素视为 `1`,不等于的视为 `-1`
2. 问题转化为:统计元素和 严格大于 0 的子数组个数
3. 使用前缀和 + 树状数组(Fenwick Tree/BIT)来高效求解

关键转换:
- 设前缀和为 `s`,子数组 `[l, r]` 的和为 `s[r+1] - s[l]`
- 要求 `s[r+1] - s[l] > 0`,即 `s[r+1] > s[l]`
- 枚举右端点,用树状数组维护之前出现过的前缀和,查询小于当前前缀和的数量

C 语言实现

```c
#include <stdlib.h>
#include <string.h>

// 树状数组 (Fenwick Tree / Binary Indexed Tree)
typedef struct {
int n;
long long *c; // 使用 long long 防止溢出
} BIT;

// 初始化树状数组
BIT* bitCreate(int n) {
BIT *bit = (BIT*)malloc(sizeof(BIT));
bit->n = n;
bit->c = (long long*)calloc(n + 1, sizeof(long long));
return bit;
}

// 释放树状数组
void bitFree(BIT *bit) {
free(bit->c);
free(bit);
}

// 单点更新:在位置 x 增加 delta
void bitUpdate(BIT *bit, int x, long long delta) {
while (x <= bit->n) {
bit->c[x] += delta;
x += x & -x; // 加上 lowbit
}
}

// 前缀查询:查询 [1, x] 的和
long long bitQuery(BIT *bit, int x) {
long long res = 0;
while (x > 0) {
res += bit->c[x];
x -= x & -x; // 减去 lowbit
}
return res;
}

/**
* 统计主要元素子数组数目 II
* @param nums 整数数组
* @param numsSize 数组长度
* @param target 目标元素
* @return 满足条件的子数组数目
*/
long long countMajoritySubarrays(int* nums, int numsSize, int target) {
// 前缀和范围: [-n, n],整体右移 n+1 个单位变为 [1, 2n+1]
int offset = numsSize + 1; // 偏移量
int size = 2 * numsSize + 1; // 树状数组大小

BIT *bit = bitCreate(size);

// 初始前缀和为 0,对应位置 offset,计数为 1
bitUpdate(bit, offset, 1);

long long ans = 0;
int s = offset; // 当前前缀和(已偏移)

for (int i = 0; i < numsSize; i++) {
// 等于 target 则 +1,否则 -1
s += (nums[i] == target) ? 1 : -1;

// 查询前缀和小于当前 s 的数量(即查询 [1, s-1] 的和)
ans += bitQuery(bit, s - 1);

// 将当前前缀和加入树状数组
bitUpdate(bit, s, 1);
}

bitFree(bit);
return ans;
}
```

复杂度分析

指标 复杂度
时间复杂度 O(n log n),每个元素进行两次树状数组操作,每次 O(log n)
空间复杂度 O(n),树状数组需要 2n+1 的空间

思路详解

1. 问题转换:设子数组中 `target` 出现 `cnt` 次,长度为 `len`。条件 `cnt > len/2` 等价于 `2*cnt > len`。令 `target` 为 `1`,其他为 `-1`,则子数组和 `> 0` 即满足条件。

2. 前缀和:设前缀和数组 `pre[i]` 表示前 `i` 个元素的和。子数组 `[l, r]` 的和为 `pre[r+1] - pre[l]`。

3. 树状数组维护:枚举右端点 `r`,需要找满足 `pre[l] < pre[r+1]` 的左端点 `l` 的数量。用树状数组维护之前所有前缀和的出现次数,支持:
- `query(x)`:查询小于等于 `x` 的前缀和个数
- `update(x, 1)`:将当前前缀和加入

4. 偏移处理:前缀和范围是 `[-n, n]`,树状数组下标从 1 开始,所以整体偏移 `n+1`。

http://www.jsqmd.com/news/1272709/

相关文章:

  • Linux网络排查利器:ss命令原理、实战与netstat替代指南
  • C++二进制文件操作:深入解析std::string序列化原理与避坑指南
  • 光伏发电系统仿真与变步长MPPT算法实践
  • 推动技术成果转化 让创新落地服务实际需求
  • Dify安装与Ollama模型接入
  • 基于Matlab的移动机器人路径规划与PID控制仿真
  • 得物App sign签名逆向:MD5加密常见错误与排查方案详解
  • 国产SPC工具在离散制造中的动态控制与边缘计算应用
  • C 语言循环与自增运算符组合对比分析
  • LangChain Memory机制详解与应用实践
  • LLM结构化输出对回答多样性的影响与平衡策略
  • 羽毛球剪辑算法集锦
  • C++异常处理终极防线:std::terminate触发机制与二次异常规避
  • 大模型技术全解析:从理论到工程实践
  • 使用JPEXS FFDec逆向分析SWF文件中的自定义加密算法与密钥生成
  • AI大模型应用开发工程师:技术落地与商业价值
  • 微信防撤回补丁失效?逆向工程实战:从内存修改到开源方案
  • Python历史事件爬虫系统:架构设计与实战技巧
  • 平衡二叉树、相交链表与随机指针链表的LeetCode经典题解析
  • AI治理中的技术尊严:易经三原则与动态伦理评估
  • 千笔AI如何解决MBA论文写作五大痛点
  • 上海做宴会厅隔断的厂家哪个好 2026年正规厂家实力与用户口碑 - 工业品牌热点
  • AIGC检测与抄袭检测的技术差异与应用实践
  • TMS320C30同步串口实现异步RS-232通信的软硬件协同设计
  • 你的 self.name = value 为何“绕道”了?——Python 数据描述符的优先级霸权与实例属性消失之谜
  • TI多核SoC处理器追踪实战:从Cortex-A15到EVE的调试与性能优化
  • 智能体技术提升个人效率的实践与优化
  • 白山房屋漏水维修养护贴士(2026 新版):卫生间/厨房/阳台漏水急症随时上门维修 - 北京金修达天津维修部
  • Spring Boot @Value注解配置注入详解与实战
  • 深入解析AM389x高性能MPU:架构、外设与嵌入式开发实战