排序大小运行超时优化

问题描述

  给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出。

输入格式

  输入的第一行包含一个整数n,表示给定数字的个数。
  第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所给定的整数。

输出格式

  输出多行,每行包含两个整数,分别表示一个给定的整数和它出现的次数。按出现次数递减的顺序输出。如果两个整数出现的次数一样多,则先输出值较小的,然后输出值较大的。

样例输入

12
5 2 3 3 1 3 4 2 5 2 3 5

样例输出

3 4
2 3
5 3
1 1
4 1

评测用例规模与约定

  1 ≤ n ≤ 1000,给出的数都是不超过1000的非负整数。

#include <stdio.h>

int main() {
    int n; // 输入的整数个数
    int i, j, k = 1, d, temp;
    int a[1000]; // 存储输入的整数
    int b[1000], c[1000]; // b[i] 表示整数 c[i] 出现的次数

    scanf("%d", &n); // 读入整数个数
    for (i = 1; i <= n; i++) {
        scanf("%d", &a[i]); // 读入整数
        b[i] = 0;
        c[i] = 0;
    }

    // 对整数进行排序
    for (i = 1; i <= n; i++) {
        for (j = i + 1; j <= n; j++)
            if (a[i] > a[j]) {
                temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
    }

    // 统计每个整数出现的次数
    for (i = 1; i <= n;) {
        for (j = i; j <= n; j++) {
            if (a[i] == a[j]) {
                c[k] = a[i];
                b[k]++;
            }
            if (a[i] != a[j]) {
                i = j;
                k++;
            }
        }
    }

    // 按照出现次数递减的顺序排序
    for (i = 1; i <= k; i++) {
        for (j = i + 1; j <= k; j++)
            if (b[i] < b[j]) {
                temp = c[i];
                c[i] = c[j];
                c[j] = temp;
                temp = b[i];
                b[i] = b[j];
                b[j] = temp;
            } else if (b[i] == b[j] && c[i] > c[j]) { // 如果出现次数相同,则按照值的大小排序
                temp = c[i];
                c[i] = c[j];
                c[j] = temp;
            }
    }

    // 输出结果
    for (i = 1; i < k; i++) {
        printf("%d %d\n", c[i], b[i]);
    }
}

结果报错运行超时

改进优化

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

#define MAXN 1000 // 定义数组的最大长度

int a[MAXN + 1]; // 存储输入的整数
int b[MAXN + 1];
int c[MAXN + 1]; // 存储不同的整数
int cnt[MAXN + 1]; // cnt[i] 表示整数 i 出现的次数

// 比较函数,用于快速排序
int cmp(const void *a, const void *b) {
    int x = *(int *)a;
    int y = *(int *)b;
    if (cnt[x] != cnt[y]) { // 如果出现次数不同,则按照出现次数排序
        return cnt[y] - cnt[x];
    } else { // 如果出现次数相同,则按照值的大小排序
        return x - y;
    }
}

int main() {
    int n; // 输入的整数个数
    scanf("%d", &n); // 读入整数个数
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]); // 读入整数
        cnt[a[i]]++; // 统计每个整数出现的次数
    }
    int k = 0; // 不同整数的个数
    for (int i = 1; i <= MAXN; i++) {
        if (cnt[i] > 0) { // 如果整数 i 出现过
            c[++k] = i; // 将其存入数组 c 中
        }
    }
    qsort(c + 1, k, sizeof(int), cmp); // 使用快速排序对数组 c 进行排序
    for (int i = 1; i <= k; i++) { // 输出结果
        printf("%d %d\n", c[i], cnt[c[i]]);
    }
}

快速排序(QuickSort)是一种基于分治策略的排序算法。它通过选择一个基准元素(pivot),然后将给定数组中的其他元素分成两个子数组,根据它们是否小于或大于基准元素来进行划分。快速排序的关键过程是划分(partition)。划分的目标是将基准元素放在其在已排序数组中的正确位置,并将所有小于基准元素的元素放在基准元素的左边,所有大于基准元素的元素放在基准元素的右边。划分过程会递归地在基准元素两侧的子数组上进行,最终完成整个数组的排序 ¹。

哈希表(Hash Table)也称为哈希映射(Hash Map),是一种实现关联数组或字典的数据结构。它是一种抽象数据类型,用于将键映射到值。哈希表使用哈希函数来计算索引,也称为哈希码,然后根据索引在桶或槽的数组中查找所需的值。在查找时,键被哈希,生成的哈希值指示存储相应值的位置。理想情况下,哈希函数会将每个键分配到唯一的桶中,但大多数哈希表设计都采用不完美的哈希函数,这可能导致哈希冲突,即哈希函数为多个键生成相同的索引。这些冲突通常以某种方式进行处理。在设计良好的哈希表中,每次查找的平均时间复杂度与存储在表中的元素数量无关 ⁵。

快速排序和哈希表都可以用来优化算法。例如,在上面给出的代码中,我们使用快速排序来对整数进行排序,并使用哈希表来统计每个整数出现的次数。这样可以大大提高算法的效率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值