You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode TwoSum哈希表实现数组越界运行时错误求助

问题排查:TwoSum哈希表实现的负索引运行时错误

我在LeetCode提交的TwoSum哈希表实现出现运行时错误:runtime error: index -576 out of bounds for type 'int [10000]',错误定位在hash_search()函数的第一行代码:

if(hash_arr[(n + TABLE_SIZE/2) % TABLE_SIZE] != -1){}

我推测是测试用例运行时出现了非法负索引,但无法复现该场景。作为C语言新手,搜索同类问题后仍未解决,请求帮助排查索引问题,完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TABLE_SIZE 10000

static int hash_arr[TABLE_SIZE];
int hash_insert();
void hash_init();
int hash_search();


// LeetCode function
//
// ret_arr[] is the array of two elements with the indices of the
// values that add up to the target value.
int *twoSum(int *nums, int numsSize, int target, int *returnSize){

    int i, j;
    int *ret_arr = (int*)malloc(2 * sizeof(int));

    // Validation
    if(ret_arr == NULL){
        *returnSize = 0;
        return NULL;
    }

    hash_init();

    for(i = 0; i < numsSize; i++){
        if((j = hash_search(target - nums[i])) == -1){
            hash_insert(nums[i], i);
        }else{
            // if j is already in the hash table
            ret_arr[0] = i;
            ret_arr[1] = j;
            *returnSize = 2;
            return ret_arr;
        }
    }
    *returnSize = 0;
    free(ret_arr);
    return NULL;
}

// int main(void) for testing purposes
int main(void){

    int nums[4] = {2,7,11,15};
    int numsSize = sizeof(nums)/sizeof(nums[0]);
    int returnSize = 0;
    int target = 9;
    int *p = NULL;

    p = twoSum(nums, numsSize, target, &returnSize);

    if(returnSize == 0){
        printf("Not found\n");
    }else{
        printf("Found at indices %d and %d\n", p[0], p[1]);
        free(p);
    }
}

// Initialization
void hash_init(){
    for(int i = 0; i < TABLE_SIZE; i++){
        hash_arr[i] = -1;
    }
}


int hash_insert(int n, int j){
    // location available
    if(hash_arr[(n + TABLE_SIZE/2) % TABLE_SIZE] == -1){
        hash_arr[(n + TABLE_SIZE/2) % TABLE_SIZE] = j;
        return 0;
    }else{
        // if location already being used
        return -1;
    }
}

int hash_search(int n){
    if(hash_arr[(n + TABLE_SIZE/2) % TABLE_SIZE] != -1){
        return hash_arr[(n + TABLE_SIZE/2) % TABLE_SIZE];
    }else{
        return -1;
    }
}

问题根源

C语言中,负数取模的结果仍为负数。当n的绝对值大于TABLE_SIZE/2时,n + TABLE_SIZE/2会变成负数,此时对TABLE_SIZE取模得到的结果还是负数,直接作为数组索引就会触发越界错误。

举个例子:当n = -6000,TABLE_SIZE=10000,TABLE_SIZE/2=5000,计算-6000 + 5000 = -1000,-1000 % 10000在C中的结果是-1000,这显然是非法的数组索引。

修复方案

要确保哈希计算结果始终是非负数,只需在取模后加上TABLE_SIZE,再取一次模,就能保证结果落在0到TABLE_SIZE-1的合法范围内:

修改哈希索引的计算表达式为:

((n + TABLE_SIZE/2) % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE

修改后的hash_insert函数

int hash_insert(int n, int j){
    int idx = ((n + TABLE_SIZE/2) % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE;
    if(hash_arr[idx] == -1){
        hash_arr[idx] = j;
        return 0;
    }else{
        return -1;
    }
}

修改后的hash_search函数

int hash_search(int n){
    int idx = ((n + TABLE_SIZE/2) % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE;
    if(hash_arr[idx] != -1){
        return hash_arr[idx];
    }else{
        return -1;
    }
}

额外优化建议

当前实现还有一个隐患:没有处理哈希冲突。当不同的n计算出相同索引时,直接返回插入失败,会导致部分测试用例无法通过。可以用线性探测法解决冲突,同时,当前哈希表只存储索引,无法验证对应的值是否匹配目标值,容易出现错误匹配,建议改用结构体存储键值对:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> // 引入INT_MIN

#define TABLE_SIZE 10000

typedef struct {
    int val;
    int idx;
} HashEntry;

static HashEntry hash_arr[TABLE_SIZE];
int hash_insert(int n, int j);
void hash_init();
int hash_search(int n);

int *twoSum(int *nums, int numsSize, int target, int *returnSize){
    int i, j;
    int *ret_arr = (int*)malloc(2 * sizeof(int));

    if(ret_arr == NULL){
        *returnSize = 0;
        return NULL;
    }

    hash_init();

    for(i = 0; i < numsSize; i++){
        if((j = hash_search(target - nums[i])) == -1){
            hash_insert(nums[i], i);
        }else{
            ret_arr[0] = j;
            ret_arr[1] = i;
            *returnSize = 2;
            return ret_arr;
        }
    }
    *returnSize = 0;
    free(ret_arr);
    return NULL;
}

void hash_init(){
    for(int i = 0; i < TABLE_SIZE; i++){
        hash_arr[i].val = INT_MIN; // 用INT_MIN标记空位置
        hash_arr[i].idx = -1;
    }
}

int hash_insert(int n, int j){
    int idx = ((n + TABLE_SIZE/2) % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE;
    // 线性探测找可用位置
    for(int i = 0; i < TABLE_SIZE; i++){
        int current_idx = (idx + i) % TABLE_SIZE;
        if(hash_arr[current_idx].val == INT_MIN){
            hash_arr[current_idx].val = n;
            hash_arr[current_idx].idx = j;
            return 0;
        }
    }
    return -1;
}

int hash_search(int n){
    int idx = ((n + TABLE_SIZE/2) % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE;
    for(int i = 0; i < TABLE_SIZE; i++){
        int current_idx = (idx + i) % TABLE_SIZE;
        if(hash_arr[current_idx].val == INT_MIN){
            return -1; // 空位置,说明不存在
        }
        if(hash_arr[current_idx].val == n){
            return hash_arr[current_idx].idx;
        }
    }
    return -1;
}

这个版本既解决了负索引问题,又处理了哈希冲突,还能准确验证目标值,通过所有LeetCode测试用例的概率更高。

内容的提问来源于stack exchange,提问作者Fiboniz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:45:36