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

HackerRank Nikita and the Game代码段错误排查求助(无调试器)

Debugging Segmentation Fault in "Nikita and the Game" Solution (HackerRank)

Let's break down why your code is hitting a segmentation fault, and walk through how to fix it—plus strategies for debugging such issues in competitive programming when you can't access test cases or debuggers.

First, the Root Cause of Your Segmentation Fault

Your code runs into an infinite recursion loop that causes a stack overflow, which triggers the segmentation fault. Here's exactly how that happens:

  1. Invalid Split Allowing Empty Subarrays:
    The isPossible function is designed to find a split point where the left and right sums are equal, but it allows splitting into a non-empty left subarray and an empty right subarray (when mid == end). For example, if you have a single element 0:

    • pre_sum becomes [0, 0]
    • calcAns is called with start=1, end=1
    • isPossible checks mid=1, calculates left sum as pre_sum[1]-pre_sum[0] = 0, right sum as pre_sum[1]-pre_sum[1] = 0
    • It returns idx=1, so calcAns recursively calls itself with start=1, end=1 (the same interval)
    • This loop repeats infinitely until the program runs out of stack space, causing a segmentation fault.
  2. Missing Termination Condition for Small Intervals:
    Your calcAns function doesn't check if the interval is too small to split (length 1 or 0). Even if you fix the split logic, without this check, you might still end up with unnecessary recursive calls.

Fixed Code

Here's the corrected version of your code with explanations of the changes:

#include <bits/stdc++.h>
#define lld long long
using namespace std;

lld isPossible(vector<lld>& pre_sum, lld start, lld end) {
    lld low = start - 1;
    lld high = end;
    // We only look for splits that create TWO NON-EMPTY subarrays, so mid must be < end
    while (start < end) {
        lld mid = (start + end) / 2;
        lld left_sum = pre_sum[mid] - pre_sum[low];
        lld right_sum = pre_sum[high] - pre_sum[mid];
        
        if (left_sum == right_sum) {
            return mid;
        } else if (left_sum < right_sum) {
            start = mid + 1;
        } else {
            end = mid;
        }
    }
    // No valid split found (or interval is too small to split)
    return -1;
}

lld calcAns(vector<lld>& pre_sum, lld start, lld end) {
    // Terminate early if interval can't be split into two non-empty parts
    if (start >= end) {
        return 0;
    }
    
    lld idx = isPossible(pre_sum, start, end);
    if (idx == -1) {
        return 0;
    }
    // Recurse on both valid subarrays
    return 1 + max(calcAns(pre_sum, start, idx), calcAns(pre_sum, idx + 1, end));
}

lld arraySplitting(vector<lld> arr) {
    vector<lld> pre_sum(arr.size() + 1);
    pre_sum[0] = 0;
    for (lld i = 0; i < arr.size(); i++) {
        pre_sum[i + 1] = pre_sum[i] + arr[i];
    }
    return calcAns(pre_sum, 1, pre_sum.size() - 1);
}

int main() {
    lld t;
    cin >> t;
    for (lld t_itr = 0; t_itr < t; t_itr++) {
        lld arr_count;
        cin >> arr_count;
        vector<lld> arr(arr_count);
        for (lld arr_itr = 0; arr_itr < arr_count; arr_itr++) {
            lld arr_item;
            cin >> arr_item;
            arr[arr_itr] = arr_item;
        }
        cout << arraySplitting(arr) << "\n";
    }
    return 0;
}

Key changes made:

  • Updated isPossible to only search for splits where mid < end (ensuring both subarrays are non-empty)
  • Added an early termination condition in calcAns for intervals that can't be split (start >= end)
  • Fixed the binary search logic to avoid skipping potential split points (changed end = mid-1 to end = mid when left sum is larger)

Strategies for Debugging Segmentation Faults in Competitive Programming

When you can't access test cases or debuggers, use these tactics to narrow down the issue:

  • Test Extreme Edge Cases Manually:

    • Single-element arrays (especially with 0)
    • All-zero arrays
    • Large arrays (to check for stack overflow from deep recursion)
    • Arrays with maximum/minimum possible values (to check for integer overflow)
  • Validate Recursion Termination:

    • Ensure every recursive path has a clear exit condition. For example, in your code, adding if (start >= end) return 0 stops infinite loops on small intervals.
    • Print recursive parameters (like start and end) to see if you're repeating the same interval infinitely.
  • Check Array Index Bounds:

    • Verify all array accesses are within valid ranges. For example, pre_sum has indices from 0 to arr.size(), so any access outside this range will cause a segfault.
  • Replace Recursion with Iteration (If Needed):

    • If you suspect stack overflow from deep recursion, rewrite the recursive logic using a stack/queue data structure to simulate recursion iteratively. This avoids hitting stack limits.
  • Check for Integer Overflow:

    • Even if it doesn't cause a segfault directly, overflow can lead to incorrect values that trigger invalid array accesses or wrong split decisions. Use larger data types (like long long) if needed.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:02:48