iT邦幫忙

0

【LeetCode with C: A Series of Problem-Solving Techniques】-- Top K Frequent Elements

  • 分享至 

  • xImage
  •  

Description

  1. Top K Frequent Elements

Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

Example 1:

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

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

Constraints:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
k is in the range [1, the number of unique elements in the array].
It is guaranteed that the answer is unique.

Follow up: Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

Answer & Explaining

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

// 定義hash table的結構
typedef struct {
    int key;   // 元素的值
    int count; // 元素出現的次數
} HashTable;


int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
    // 1. 使用hash table統計每個元素的出現頻率
    HashTable* hashTable = (HashTable*)malloc(numsSize * sizeof(HashTable)); // 分配hash table的空間
    int hashTableSize = 0; // hash table的大小初始化為0
    for (int i = 0; i < numsSize; i++) { // 遍歷數組
        int found = 0; // 記錄當前元素是否已在hash table中
        for (int j = 0; j < hashTableSize; j++) { // 遍歷hash table
            if (hashTable[j].key == nums[i]) { // 如果元素已經在hash table中
                hashTable[j].count++; // 增加其出現次數
                found = 1; // 標記為已找到
                break; // 結束當前loop
            }
        }
        if (!found) { // 如果元素不在hash table中
            hashTable[hashTableSize].key = nums[i]; // 將元素添加到hash table
            hashTable[hashTableSize].count = 1; // 並設置其出現次數為1
            hashTableSize++; // 增加hash table的大小
        }
    }

    // 2. 使用bucket排序
    int maxCount = numsSize; // 設定bucket數組的最大大小為數組的大小
    int** buckets = (int**)malloc((maxCount + 1) * sizeof(int*)); // 分配bucket數組的空間
    int* bucketSizes = (int*)calloc((maxCount + 1), sizeof(int)); // 初始化每個bucket的大小為0
    
    // 計算每個bucket的大小
    for (int i = 0; i < hashTableSize; i++) { // 遍歷hash table
        int count = hashTable[i].count; // 取得當前元素的出現次數
        bucketSizes[count]++; // 將對應bucket的大小加1
    }
    
    // 分配bucket的空間
    for (int i = 0; i <= maxCount; i++) { // 遍歷每個bucket
        if (bucketSizes[i] > 0) { // 如果bucket的大小大於0
            buckets[i] = (int*)malloc(bucketSizes[i] * sizeof(int)); // 為bucket分配空間
            bucketSizes[i] = 0; // 重置bucket的大小為0,用於之後存放元素
        }
    }
    
    // 將元素放入bucket中
    for (int i = 0; i < hashTableSize; i++) { // 遍歷hash table
        int count = hashTable[i].count; // 取得當前元素的出現次數
        buckets[count][bucketSizes[count]++] = hashTable[i].key; // 將元素放入對應頻率的bucket中
    }

    // 3. 收集結果
    int* result = (int*)malloc(k * sizeof(int)); // 分配result 陣列的空間
    *returnSize = 0; // 初始化返回的結果大小為0
    for (int i = maxCount; i >= 0 && *returnSize < k; i--) { // 從後向前遍歷bucket數組
        for (int j = 0; j < bucketSizes[i] && *returnSize < k; j++) { // 遍歷每個bucket中的元素
            result[(*returnSize)++] = buckets[i][j]; // 將頻率最高的元素加入result
        }
    }

    // 釋放memory
    for (int i = 0; i <= maxCount; i++) { // 遍歷每個bucket
        if (bucketSizes[i] > 0) { // 如果bucket的大小大於0
            free(buckets[i]); // 釋放bucket的memory
        }
    }
    free(buckets); // 釋放bucket數組的memory
    free(bucketSizes); // 釋放bucket大小數組的memory
    free(hashTable); // 釋放hash table的memory

    return result; 
}

Testing

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

// 定義hash table的結構
typedef struct {
    int key;   // 元素的值
    int count; // 元素出現的次數
} HashTable;


int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
    // 1. 使用hash table統計每個元素的出現頻率
    HashTable* hashTable = (HashTable*)malloc(numsSize * sizeof(HashTable)); // 分配hash table的空間
    int hashTableSize = 0; // hash table的大小初始化為0
    for (int i = 0; i < numsSize; i++) { // 遍歷數組
        int found = 0; // 記錄當前元素是否已在hash table中
        for (int j = 0; j < hashTableSize; j++) { // 遍歷hash table
            if (hashTable[j].key == nums[i]) { // 如果元素已經在hash table中
                hashTable[j].count++; // 增加其出現次數
                found = 1; // 標記為已找到
                break; // 結束當前loop
            }
        }
        if (!found) { // 如果元素不在hash table中
            hashTable[hashTableSize].key = nums[i]; // 將元素添加到hash table
            hashTable[hashTableSize].count = 1; // 並設置其出現次數為1
            hashTableSize++; // 增加hash table的大小
        }
    }

    // 2. 使用bucket排序
    int maxCount = numsSize; // 設定bucket數組的最大大小為數組的大小
    int** buckets = (int**)malloc((maxCount + 1) * sizeof(int*)); // 分配bucket數組的空間
    int* bucketSizes = (int*)calloc((maxCount + 1), sizeof(int)); // 初始化每個bucket的大小為0
    
    // 計算每個bucket的大小
    for (int i = 0; i < hashTableSize; i++) { // 遍歷hash table
        int count = hashTable[i].count; // 取得當前元素的出現次數
        bucketSizes[count]++; // 將對應bucket的大小加1
    }
    
    // 分配bucket的空間
    for (int i = 0; i <= maxCount; i++) { // 遍歷每個bucket
        if (bucketSizes[i] > 0) { // 如果bucket的大小大於0
            buckets[i] = (int*)malloc(bucketSizes[i] * sizeof(int)); // 為bucket分配空間
            bucketSizes[i] = 0; // 重置bucket的大小為0,用於之後存放元素
        }
    }
    
    // 將元素放入bucket中
    for (int i = 0; i < hashTableSize; i++) { // 遍歷hash table
        int count = hashTable[i].count; // 取得當前元素的出現次數
        buckets[count][bucketSizes[count]++] = hashTable[i].key; // 將元素放入對應頻率的bucket中
    }

    // 3. 收集結果
    int* result = (int*)malloc(k * sizeof(int)); // 分配result 陣列的空間
    *returnSize = 0; // 初始化返回的結果大小為0
    for (int i = maxCount; i >= 0 && *returnSize < k; i--) { // 從後向前遍歷bucket數組
        for (int j = 0; j < bucketSizes[i] && *returnSize < k; j++) { // 遍歷每個bucket中的元素
            result[(*returnSize)++] = buckets[i][j]; // 將頻率最高的元素加入result
        }
    }

    // 釋放memory
    for (int i = 0; i <= maxCount; i++) { // 遍歷每個bucket
        if (bucketSizes[i] > 0) { // 如果bucket的大小大於0
            free(buckets[i]); // 釋放bucket的memory
        }
    }
    free(buckets); // 釋放bucket數組的memory
    free(bucketSizes); // 釋放bucket大小數組的memory
    free(hashTable); // 釋放hash table的memory

    return result; 
}

// 測試函數
int main() {
    int nums1[] = {1, 1, 1, 2, 2, 3}; // 測試數據1
    int nums2[] = {1}; // 測試數據2
    int returnSize; // 用於存儲返回結果的大小
    
    int* result1 = topKFrequent(nums1, 6, 2, &returnSize); // 求前2個最常出現的元素
    printf("Top 2 frequent elements: ");
    for (int i = 0; i < returnSize; i++) { // 輸出結果
        printf("%d ", result1[i]);
    }
    printf("\n");
    free(result1); // 釋放結果數組的memory
    
    int* result2 = topKFrequent(nums2, 1, 1, &returnSize); // 求前1個最常出現的元素
    printf("Top 1 frequent element: ");
    for (int i = 0; i < returnSize; i++) { // 輸出結果
        printf("%d ", result2[i]);
    }
    printf("\n");
    free(result2); // 釋放結果數組的memory
    
    return 0;
}

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言