LeetCode 1416 Restore The Array问题:代码无法通过第83个长字符串测试用例的原因分析求助
嗨,我来帮你拆解下你的C代码和那篇能全过的C++代码之间的核心差异,以及为啥你的代码卡在长字符串测试用例上~
核心问题1:数字构建时的溢出bug(最关键)
你的代码里用atoi转换子字符串来得到数字,但atoi返回的是int类型。当输入字符串里的数字长度接近或超过int的上限(比如32位int最大是2147483647),就会发生溢出,得到错误的数值(比如变成负数或者不符合预期的正数)。这时候你的代码会错误地判断这个数大于k,提前跳出循环,漏掉大量合法的拆分方式,结果自然就错了。
而那篇C++代码用long long类型逐步构建数字(currNum = (currNum * 10) + currDig),long long的范围能到9e18,完全覆盖题目中k的上限(题目里k≤1e9),不会出现溢出,能准确判断数字是否在1到k的合法范围内。
核心问题2:频繁内存分配导致的性能损耗
你的代码在循环里每次都malloc子字符串、memcpy再free,对于超长输入字符串来说,这种频繁的内存操作会带来极大的性能开销,很可能导致超时(尤其是第83个测试用例是大字符串的场景)。而C++代码直接通过字符计算构建数字,不需要额外内存分配,效率高很多。
前导零处理:逻辑没问题但可以优化
你的循环条件里的s[i] != '0'能正确跳过前导零的情况(因为前导零的数字不合法),这部分逻辑和C++代码里currNum <1就break的效果一致。不过可以改成更直观的写法:比如先判断如果s[i] == '0',直接返回0(因为以0开头的数字无法作为合法拆分的一部分),可读性会更好。
给你的代码修改建议
把数字构建改成用long long逐步计算,去掉冗余的内存分配,修改后的dp函数核心循环部分如下:
int dp(char* s, int length, int k, int i, int prevNum) { int result; if (i == length) { return 1; } if (mem[i] != -1) { return mem[i] % MOD; } result = 0; long long num = 0; // 用long long存储当前构建的数字,避免溢出 // 去掉s[i] != '0'的循环条件,转而在循环内判断前导零 for (int posLength = 1; posLength <= kLength && posLength <= length - i; posLength++) { num = num * 10 + (s[i + posLength - 1] - '0'); // 数字小于1(比如前导零的情况)或者超过k,直接跳出 if (num < 1 || num > k) { break; } result = (result + dp(s, length, k, i + posLength, num)) % MOD; } result %= MOD; return mem[i] = result; }
这样修改后,既解决了溢出问题,又提升了性能,应该就能通过所有测试用例啦~
备注:内容来源于stack exchange,提问作者Sagi Sason

