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

Perm函数及C语言移位统计程序无法处理长数字,求优化建议

问题描述

需要实现程序:从标准输入读取自然数数量N,再读取N个自然数,统计其中可通过数字移位转换为其他输入数字的数量。示例输入:6,随后输入25 21 10242 42210 52 24021,输出应为5。

现有C语言代码存在两个问题:无法处理较长数字,且怀疑qsort并非最优方案,寻求改进建议。

现有代码

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

typedef unsigned long long int cache;

int cmp(const void * a, const void * b) {
    return ( *(int*)a - *(int*)b );
}

int main() {
    int n, i, j, count_equals = 0;
    char num[22];
    scanf("%d", &n);
    cache * A = (cache *) malloc(n * sizeof(cache));
    for (i = 0; i < n; i++) {
        scanf("%s", num);
        qsort(num, strlen(num), sizeof(char), cmp);
        for (A[i] = num[--j] - '0'; --j >= 0; A[i] = A[i] * 10 + (num[j] - '0'));
    }
    qsort(A, n, sizeof(cache), cmp);
    for (j = 0, i = 1; i < n; i++) {
        if (A[i] == A[i - 1]) { 
            count_equals++;
        } else if (count_equals) {
            j += ++count_equals, count_equals = 0;
        }
    }
    if (count_equals) {
        j += ++count_equals;
    } 
    free(A);
    printf("%d\n", j);
    return 0;
}

改进建议

1. 解决长数字溢出问题

原代码用unsigned long long存储排序后的数字,当数字长度超过19位时会溢出(unsigned long long最大值为18446744073709551615,仅20位,有效数字最多19位)。优化方案:

  • 直接用字符串保存排序后的数字作为特征键,无论数字多长都不会溢出,无需转换为数值类型。
  • 修复原代码中j未初始化的bug:在生成特征键前,必须先将j赋值为字符串长度,否则会出现数组越界的未定义行为。

2. 替换qsort的更优方案:哈希表统计

原代码两次使用qsort,时间复杂度为O(N log N + NM log M)(M为数字平均长度)。改用哈希表统计相同特征键的数字数量,平均时间复杂度可优化为O(NM log M):

  • 哈希表的插入、查找操作平均时间复杂度为O(1),无需对所有特征键排序,仅需对每个数字的字符排序生成特征键。
  • 遍历哈希表时,对每个出现次数≥2的特征键,累加其出现次数即可得到符合条件的数字总数。

改进后的示例代码

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

// 哈希表节点结构
typedef struct HashNode {
    char* key;
    int count;
    struct HashNode* next;
} HashNode;

// 字符串哈希函数
unsigned int hash(const char* str) {
    unsigned int h = 0;
    while (*str) {
        h = h * 31 + *str++;
    }
    return h % 1009; // 选用质数作为哈希表大小,减少冲突
}

// 在哈希表中查找键,不存在则插入新节点
HashNode* find_or_insert(HashNode** table, const char* key) {
    unsigned int idx = hash(key);
    HashNode* node = table[idx];
    while (node) {
        if (strcmp(node->key, key) == 0) {
            return node;
        }
        node = node->next;
    }
    // 插入新节点
    node = (HashNode*)malloc(sizeof(HashNode));
    node->key = strdup(key);
    node->count = 1;
    node->next = table[idx];
    table[idx] = node;
    return node;
}

// 字符排序比较函数
int cmp_char(const void* a, const void* b) {
    return *(char*)a - *(char*)b;
}

int main() {
    int n, i, result = 0;
    char num[100]; // 支持更长的数字输入
    HashNode* hash_table[1009] = {NULL}; // 初始化哈希表

    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%s", num);
        int len = strlen(num);
        qsort(num, len, sizeof(char), cmp_char); // 生成特征键:排序后的字符数组
        HashNode* node = find_or_insert(hash_table, num);
        node->count++;
    }

    // 遍历哈希表统计结果
    for (i = 0; i < 1009; i++) {
        HashNode* node = hash_table[i];
        while (node) {
            if (node->count >= 2) {
                result += node->count;
            }
            // 释放内存
            HashNode* temp = node;
            node = node->next;
            free(temp->key);
            free(temp);
        }
    }

    printf("%d\n", result);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:21:57