LeetCode 219. 存在重复元素 II(C语言详解)

一、题目描述

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 ij ,满足:

  • nums[i] == nums[j]

  • abs(i - j) <= k

如果存在,返回 true;否则返回 false

示例 1

复制代码
输入:nums = [1,2,3,1], k = 3
输出:true

解释:

复制代码
nums[0] = nums[3] = 1
|0 - 3| = 3 <= k

示例 2

复制代码
输入:nums = [1,0,1,1], k = 1
输出:true

示例 3

复制代码
输入:nums = [1,2,3,1,2,3], k = 2
输出:false

二、解题思路

题目的核心是:

找到两个相同元素,并且它们的下标距离不超过 k

如果直接使用 两层循环

复制代码
for i
    for j=i+1 ... i+k

时间复杂度为:

复制代码
O(n*k)

n 最大为 10^5 时容易超时。

因此可以使用 哈希表 + 滑动窗口 的思想进行优化。


三、滑动窗口 + 哈希表

核心思想

维护一个 大小最多为 k 的窗口

  • 使用 哈希集合 存储窗口中的元素

  • 每次遍历 nums[i]

    • 如果当前元素已经存在于集合中 → 说明找到了重复元素

    • 否则加入集合

  • 如果窗口大小超过 k,删除最早进入窗口的元素 nums[i-k]

这样集合中始终只保存 最近 k 个元素


过程示例

复制代码
nums = [1,2,3,1]
k = 3

遍历过程:

复制代码
i=0  set={1}
i=1  set={1,2}
i=2  set={1,2,3}
i=3  发现1已经存在 -> 返回true

四、C语言实现(滑动窗口 + 哈希表)

由于 C 语言没有内置 HashSet,我们使用 链式哈希表 来实现。

复制代码
#include <stdbool.h>
#include <stdlib.h>

#define HASH_SIZE 200003

typedef struct Node {
    int val;
    struct Node* next;
} Node;

Node* hash[HASH_SIZE];

int hashFunc(int x) {
    if (x < 0) x = -x;
    return x % HASH_SIZE;
}

bool find(int val) {
    int h = hashFunc(val);
    Node* cur = hash[h];

    while (cur) {
        if (cur->val == val)
            return true;
        cur = cur->next;
    }

    return false;
}

void insert(int val) {
    int h = hashFunc(val);

    Node* node = (Node*)malloc(sizeof(Node));
    node->val = val;
    node->next = hash[h];
    hash[h] = node;
}

void removeVal(int val) {
    int h = hashFunc(val);

    Node* cur = hash[h];
    Node* pre = NULL;

    while (cur) {
        if (cur->val == val) {
            if (pre)
                pre->next = cur->next;
            else
                hash[h] = cur->next;

            free(cur);
            return;
        }

        pre = cur;
        cur = cur->next;
    }
}

bool containsNearbyDuplicate(int* nums, int numsSize, int k) {

    for (int i = 0; i < HASH_SIZE; i++)
        hash[i] = NULL;

    for (int i = 0; i < numsSize; i++) {

        if (find(nums[i]))
            return true;

        insert(nums[i]);

        if (i >= k)
            removeVal(nums[i - k]);
    }

    return false;
}

五、复杂度分析

时间复杂度

复制代码
O(n)

每个元素最多进行一次:

  • 插入

  • 查找

  • 删除


空间复杂度

复制代码
O(k)

哈希表中最多只存储 k 个元素。


六、暴力解法(不推荐)

思路

枚举每个元素,检查后面 k 个位置是否有相同元素。

代码实现

复制代码
bool containsNearbyDuplicate(int* nums, int numsSize, int k) {

    for (int i = 0; i < numsSize; i++) {
        for (int j = i + 1; j <= i + k && j < numsSize; j++) {
            if (nums[i] == nums[j])
                return true;
        }
    }

    return false;
}

复杂度

复制代码
时间复杂度:O(n*k)
空间复杂度:O(1)

n 很大时容易 超时


七、总结

本题的关键在于理解 滑动窗口思想

  • 只需要维护 最近 k 个元素

  • 使用 哈希表快速判断是否重复

核心流程:

复制代码
遍历数组
    如果元素已存在 -> 返回 true
    加入哈希表
    如果窗口超过 k -> 删除 nums[i-k]

这种 滑动窗口 + 哈希表 的技巧在很多题目中都会出现,例如:

  • LeetCode 217:存在重复元素

  • LeetCode 219:存在重复元素 II

  • LeetCode 220:存在重复元素 III

相关推荐
Shell运维手记几秒前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
船厂电气自动化ai大模型1 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
旖旎夜光1 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
叠层归一研究院2 小时前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
zlinear数据采集卡3 小时前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构
杨石兴3 小时前
31、玩具MoM:用2x2矩阵串起全套流程
人工智能·算法·矩阵·电磁学
江畔柳前堤3 小时前
Function Calling 与 Tool Calling:从认知到工程的全景深度解析
开发语言·网络·人工智能·深度学习·算法·机器学习·php
Navigator_Z3 小时前
LeetCode //C - 1192. Critical Connections in a Network
c语言·算法·leetcode
zander2584 小时前
LeetCode 739:每日温度——为什么单调栈要持续弹出
开发语言·python·算法
2601_955759884 小时前
如何降低 Claude API 批量生产返工率
大数据·人工智能·算法