超长数字串大数据集排序问题:归并排序适配长串时结果异常
解决超长数字字符串归并排序的问题
我看了你这段归并排序的代码,问题出在长度超过18的数字串比较逻辑有缺失——你只处理了两个串长度都≤18的情况,其他涉及长串的场景都没覆盖到,这就是排序结果不符合预期的核心原因。
问题场景拆解
当前代码的比较逻辑只覆盖了「两个串长度都≤18」的情况,但实际会遇到以下未处理的场景:
- 其中一个串长度>18,另一个≤18(比如长度19的串和长度18的串,显然长度长的数值更大)
- 两个串长度都>18且长度相等(这时候需要逐位比较数字大小)
修正后的比较逻辑
对于大正数字符串的比较,正确的逻辑应该是:
- 先比长度:长度更短的数字,数值一定更小
- 长度相等时:
- 若长度≤18:可以安全转成
long后比较(或者直接用BigInteger) - 若长度>18:直接用字符串的
compareTo方法即可——因为纯数字字符串的字典序和数值大小完全一致(前提是你的输入没有前导零,符合大正整数的要求)
- 若长度≤18:可以安全转成
修正后的merge方法代码
static void merge(String arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; String L[] = new String[n1]; String R[] = new String[n2]; for (int i = 0; i < n1; ++i) L[i] = arr[l + i]; for (int j = 0; j < n2; ++j) R[j] = arr[m + 1 + j]; int i = 0, j = 0; int k = l; while (i < n1 && j < n2) { // 先比较长度:长度短的数值更小 if (L[i].length() < R[j].length()) { arr[k] = L[i]; i++; } else if (L[i].length() > R[j].length()) { arr[k] = R[j]; j++; } else { // 长度相等的情况 if (L[i].length() <= 18) { // 转成long比较,避免BigInteger的额外开销 long numL = Long.parseLong(L[i]); long numR = Long.parseLong(R[j]); if (numL <= numR) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } } else { // 长度>18时,直接用字符串compareTo,字典序等于数值序 if (L[i].compareTo(R[j]) <= 0) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } } } k++; } // 处理剩余元素 while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } }
逻辑说明
- 长度比较是最直接的判断:比如"1234"(4位)肯定比"999"(3位)大,这一步优先处理能快速区分大部分情况
- 长度相等时,短串转
long比用BigInteger更高效;长串直接用字符串比较,既避免了转大数的性能损耗,又能保证正确性 - 最后补全了剩余元素的处理逻辑,确保所有子数组元素都能被正确合并
这样修改后,不管数字串长度是1还是100万,都能正确完成排序,同时保持原有的性能优势。
内容的提问来源于stack exchange,提问作者R Dhaval
相关产品推荐
相关产品推荐

