day13|leetcode|C||队列|239.滑动窗口最大值|347. 前 K 个高频元素

本文介绍了如何使用滑动窗口算法解决LeetCode中的239题(滑动窗口最大值),以及347题(前K个高频元素),涉及队列、哈希表和最小堆的数据结构应用。
摘要由CSDN通过智能技术生成

Leetcode 239.滑动窗口最大值

链接239. 滑动窗口最大值

int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
    int n = numsSize;
    int queue[n]; //队列
    int front = 0, rear = -1; //队首 队尾
    int left = 0, right = 0; //窗口左下标 窗口右下标
    while (right < n) { //窗口右移至终点
        while (rear >= front && nums[right] > queue[rear]) rear--; //维护队列的单调性(非递增),即保证队首元素就是当前窗口的最大值
        queue[++rear] = nums[right++]; //入队下一个窗口可能的最大值
        if (left + k <= right) { //窗口大小大于k
            if (nums[left] == queue[front]) front++; //如果最大值已经在窗口的左边,则将它永久出队
            else nums[left] = queue[front]; //否则记录最大值进原数组中
            left++; //左框右移
        }
    }
    *returnSize = n - k + 1;
    return nums; 
}
  1. int queue[n];:创建一个数组 queue 用来模拟队列,存储可能的最大值。
  2. int front = 0, rear = -1;:初始化队列的前后指针。
  3. int left = 0, right = 0;:初始化窗口的左右边界。
  4. while (right < n):窗口右边界移动至数组末尾,即遍历整个数组。
  5. while (rear >= front && nums[right] > queue[rear]) rear--;:维护队列的单调性(非递增),即保证队首元素就是当前窗口的最大值。在队列中,如果存在比当前元素小的元素,则将它们出队,以保证队首元素是当前窗口的最大值。
  6. queue[++rear] = nums[right++];:将当前元素入队,即入队下一个窗口可能的最大值。
  7. if (left + k <= right):当窗口大小大于等于 k 时,说明窗口形成完毕。
  8. if (nums[left] == queue[front]) front++;:如果最大值已经在窗口的左边,则将它永久出队。
  9. else nums[left] = queue[front];:否则将队首元素记录到原数组中,因为它是窗口的最大值。
  10. left++;:左边界右移,即窗口向右滑动。

最终,*returnSize 被赋值为 n - k + 1,表示最终返回的数组大小为 n - k + 1,即滑动窗口的个数。

模拟过程:

假设输入数组 nums = [1, 3, -1, -3, 5, 3, 6, 7],窗口大小 k = 3

  1. 初始化:left = 0, right = 0front = 0, rear = -1
  2. 窗口移动过程:
    • 初始窗口:[1, 3, -1],队列 [3]left = 0, right = 3,此时 front = 0, rear = 0
    • 滑动窗口:[3, -1, -3],队列 [3, -1]left = 1, right = 4,此时 front = 0, rear = 1
    • 滑动窗口:[-1, -3, 5],队列 [5]left = 2, right = 5,此时 front = 2, rear = 2
    • 滑动窗口:[-3, 5, 3],队列 [5, 3]left = 3, right = 6,此时 front = 3, rear = 4
    • 滑动窗口:[5, 3, 6],队列 [6]left = 4, right = 7,此时 front = 4, rear = 5
    • 滑动窗口:[3, 6, 7],队列 [7]left = 5, right = 8,此时 front = 5, rear = 6
  3. 返回结果为 [3, 3, 5, 5, 6, 7]

    Leetcode 347. 前 K 个高频元素

    链接347. 前 K 个高频元素

    // 定义哈希表节点结构体
    typedef struct HashNode {
        int key;
        int val;
        struct HashNode *next;
    } HashNode;
    
    // 定义哈希表结构体
    typedef struct {
        HashNode **buckets;
        int size;
    } HashMap;
    
    // 创建哈希表
    HashMap* createHashMap(int size) {
        HashMap *hashMap = (HashMap*)malloc(sizeof(HashMap));
        hashMap->size = size;
        hashMap->buckets = (HashNode**)calloc(size, sizeof(HashNode*));
        return hashMap;
    }
    
    // 哈希函数
    int hashFunction(int key, int size) {
        return abs(key) % size;
    }
    
    // 在哈希表中查找节点
    HashNode* findNode(HashMap *hashMap, int key) {
        int index = hashFunction(key, hashMap->size);
        HashNode *node = hashMap->buckets[index];
        while (node != NULL) {
            if (node->key == key)
                return node;
            node = node->next;
        }
        return NULL;
    }
    
    // 向哈希表中插入节点
    void insertNode(HashMap *hashMap, int key, int val) {
        int index = hashFunction(key, hashMap->size);
        HashNode *node = findNode(hashMap, key);
        if (node == NULL) {
            node = (HashNode*)malloc(sizeof(HashNode));
            node->key = key;
            node->val = val;
            node->next = hashMap->buckets[index];
            hashMap->buckets[index] = node;
        } else {
            node->val = val;
        }
    }
    
    // 最小堆结构体
    typedef struct {
        int key;
        int val;
    } HeapNode;
    
    // 比较函数,用于构建最小堆
    int compare(const void *a, const void *b) {
        return (*(HeapNode*)a).val - (*(HeapNode*)b).val;
    }
    
    // 返回前 k 高的元素
    int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
        // 创建哈希表并统计元素频率
        HashMap *hashMap = createHashMap(numsSize * 2);
        for (int i = 0; i < numsSize; i++) {
            HashNode *node = findNode(hashMap, nums[i]);
            if (node == NULL) {
                insertNode(hashMap, nums[i], 1);
            } else {
                node->val++;
            }
        }
        
        // 构建最小堆
        HeapNode *heap = (HeapNode*)malloc(k * sizeof(HeapNode));
        for (int i = 0; i < k; i++) {
            heap[i].key = -1;
            heap[i].val = -1;
        }
        for (int i = 0; i < hashMap->size; i++) {
            HashNode *node = hashMap->buckets[i];
            while (node != NULL) {
                if (node->val > heap[0].val || heap[0].val == -1) {
                    heap[0].key = node->key;
                    heap[0].val = node->val;
                    qsort(heap, k, sizeof(HeapNode), compare);
                }
                node = node->next;
            }
        }
        
        // 构造返回结果数组
        int *result = (int*)malloc(k * sizeof(int));
        *returnSize = k;
        for (int i = 0; i < k; i++) {
            result[i] = heap[i].key;
        }
        
        // 释放内存
        for (int i = 0; i < hashMap->size; i++) {
            HashNode *node = hashMap->buckets[i];
            while (node != NULL) {
                HashNode *temp = node;
                node = node->next;
                free(temp);
            }
        }
        free(hashMap->buckets);
        free(hashMap);
        free(heap);
        
        return result;
    }
    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值