【Leetcode&C语言】347. Top K Frequent Elements

13 篇文章 0 订阅

问题描述

Given a non-empty array of integers, return the k most frequent elements.

非空的整型数组,返回K个出现次数最频繁的元素

举例说明

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Example 2:

Input: nums = [1], k = 1
Output: [1]

注意 

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
  • It's guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique.
  • You can return the answer in any order.
  • 可以假设k是合理的,k的范围在[1,number]
  • 算法的时间复杂度必须小于O(nlogn),n为数组长度(非翻译:然而实践证明,O(nlogn)也是可以通过的)
  • 保证答案是唯一的,话句话说前k个频次最高的元素是唯一的。
  • 可以以任意顺序返回

 实现

快速排序O(nlogn) 

我原本是想使用堆实现的,然而在C语言中判断收集频次这里无论如何都需要O(n²)来实现。写到哭泣……

后来学了快速排序,发现正好可以应用上。

快速排序的平均时间复杂度和最佳时间复杂度为O(nlogn),最坏时间复杂度为O(n²)。随机选取pivot index可以避免最坏时间复杂度。

我们还需要声明新的结构体Freq用来记录数组元素和出现次数。

首先对数组进行快速排序(O(nlogn)),方便用Freq类型的数组freq记录每个元素和出现次数(O(n))。

然后对freq进行快速排序,返回前k个Freq对象的element属性即可。

这个代码十分冗余的地方是对整型数组和Freq类型的数组分别写了快速排序的函数。因为不会兼容因为他们的类型不同,so代码略长。



/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

typedef struct Freq Freq;
struct Freq{
    int element;
    int times;
};

void swap_element(int *a,int *b){
    int tmp = *a;
    *a=*b;
    *b=tmp;
}

int random_partition(int *arr, int start, int end){
    int pIndex1 = rand()%(end-start+1)+start;
    swap_element(arr+pIndex1,arr+end);
    int pivot = arr[end];
    int pIndex2 = start;
    for(int i=start;i<end;i++){
        if(arr[i]<=pivot){
            swap_element(arr+i,arr+pIndex2);
            pIndex2++;
        }
    }
    swap_element(arr+pIndex2,arr+end);
    return pIndex2;
}

void quick_sort(int *arr, int start, int end){
    if(start<end){
        int pIndex = random_partition(arr, start,end);
        printf("pIndex=%d\n",pIndex);
        quick_sort(arr,start,pIndex-1);
        quick_sort(arr,pIndex+1,end);
    }
}

//------------------------------------------------------------------------------------------------

void freq_swap_element(Freq *a,Freq *b){
    int element = a->element;
    int times = a->times;
    a->element = b->element;
    a->times = b->times;
    b->element = element;
    b->times = times;
}

int freq_random_partition(Freq *arr, int start, int end){
    int pIndex1 = rand()%(end-start+1)+start;
    freq_swap_element(arr+pIndex1,arr+end);
    int pivot = arr[end].times;
    int pIndex2 = start;
    for(int i=start;i<end;i++){
        if(arr[i].times>=pivot){
            freq_swap_element(arr+i,arr+pIndex2);
            pIndex2++;
        }
    }
    freq_swap_element(arr+pIndex2,arr+end);
    return pIndex2;
}
void freq_quick_sort(Freq *arr, int start, int end){
    if(start<end){
        int pIndex = freq_random_partition(arr, start,end);
        freq_quick_sort(arr,start,pIndex-1);
        freq_quick_sort(arr,pIndex+1,end);
    }
}

int* topKFrequent(int* nums, int numsSize, int k, int* returnSize){
    *returnSize=k;
    quick_sort(nums,0,numsSize-1);
    printf("sort done\n");
    Freq *freq = malloc(sizeof(Freq)*numsSize);
    freq[0].element=nums[0];
    freq[0].times = 1;
    int j=0;
    for(int i=1;i<numsSize;i++)
    {
        if(nums[i]==freq[j].element){
            freq[j].times++;
        }else
        {
            j++;
            freq[j].element=nums[i];
            freq[j].times = 1;
        }
    }
    printf("freq filled out\n");
    freq_quick_sort(freq,0,j);
    printf("freq sort done\n");
    int *ret = malloc(sizeof(int)*k);
    for(int i=0;i<k;i++){
        ret[i]=freq[i].element;
    }
    return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值