【代码随想录算法训练营第十三天|239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结】

滑动窗口最大值

leetcode

代码随想录

  • 单调队列:单调递增或单调递减

  • deque可以两边扩增(用数组实现)

  • 解题思路

    • 用单调递减队列只维护可能是滑动窗口最大值的数
    • 队列出口元素是滑动窗口最大值
    • pop:如果窗口移除的元素等于队列的最大值,队列弹出元素,否则不做操作
    • push:如果push的元素大于队列入口的数值,那么将队列入口的元素弹出,直到push的元素小于等于入口元素的数值为止

    239.滑动窗口最大值-2

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

int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
    int* result = malloc(sizeof(int)*(numsSize-k+1));
    int cnt = 0;
    int queue[numsSize];
    int left = 0;
    int right = 0;
    queue[0] = nums[0];

    for (int i = 1; i < k; i++) {
        while(right >= left && nums[i] > queue[right]){
                right--;
        }
        queue[++right] = nums[i];
    }
    result[cnt++] = queue[left];

    for (int j = 0; j+k < numsSize; j++){
        if (queue[left] == nums[j]){
            left++;
        }
        while(right >= left && nums[j+k] > queue[right]){
                right--;
        }
        queue[++right] = nums[j+k];
        result[cnt++] = queue[left];
    }

    *returnSize = numsSize - k + 1;

    return result;
}

前k个高频元素

leetcode

代码随想录

  • 解题思路
    • 要统计元素出现频率——哈希map
    • 对频率排序——小顶堆
    • 找出前K个高频元素——大小为K的小顶堆
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
//hash
#define MAX_SIZE 10000
 typedef struct {
    int key;
    int value;
    UT_hash_handle hh;
 }hashNode;

 hashNode* hashMap = NULL;
 int hashSize = 0;

 hashNode* hashMapFind(int key) {
    hashNode* tmp = NULL;
    HASH_FIND_INT(hashMap, &key, tmp);
    return tmp;
 }

 void hashMapAdd(int key) {
    hashNode* res = hashMapFind(key);

    if (res == NULL) {
        hashNode* tmp = malloc(sizeof(hashNode));
        tmp -> key = key;
        tmp -> value = 1;
        HASH_ADD_INT(hashMap, key, tmp);
        hashSize++;
    }
    else {
        res -> value++;
    }
 }

 void hashMapCleanUp() {
    hashNode *cur, *tmp;

    HASH_ITER(hh, hashMap, cur, tmp){
        HASH_DEL(hashMap, cur);
        free(cur);
    }
 }

//heap
typedef struct {
    int key;
    int value;
}heapNode;

typedef struct {
    int size;
    heapNode heap[MAX_SIZE];
}heap;

heap smallHeap;

bool less(int a, int b) {
    return smallHeap.heap[a].value < smallHeap.heap[b].value;
}

void swap(int a, int b) {
    heapNode tmp = smallHeap.heap[a];
    smallHeap.heap[a] = smallHeap.heap[b];
    smallHeap.heap[b] = tmp;
}

void swim(int k) {
    while (k > 1 && less(k, k/2)) {
        swap(k, k/2);
        k = k/2;
    }
}

void sink(int k) {
    while (2*k <= smallHeap.size) {
        int j = 2*k;
        if (j < smallHeap.size && less(j+1, j)) {
            j++;
        }
        if (!less(j, k)) {
            break;
        }
        swap(j, k);
        k = j;
    }
}

int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
    hashMap = NULL;
    hashNode *cur, *tmp;
    int* result = malloc(sizeof(int) * k);
    smallHeap.size = 0;

    for (int i = 0; i < numsSize; i++) {
        hashMapAdd(nums[i]);
    }

    HASH_ITER(hh, hashMap, cur, tmp) {
        if (smallHeap.size < k) {
            smallHeap.heap[++smallHeap.size].key = cur -> key;
            smallHeap.heap[smallHeap.size].value = cur -> value;
            swim(smallHeap.size);
        }
        else {
            if (smallHeap.heap[1].value < cur -> value) {
                smallHeap.heap[1].key = cur -> key;
                smallHeap.heap[1].value = cur -> value;
                sink(1);
            }
        }
    }


    hashMapCleanUp();
    *returnSize = k;
    for (int i = 1; i <= k; i++) {
        result[i-1] = smallHeap.heap[i].key;
    }

    return result;
}

全局变量在函数外只能声明或初始化,赋值要在函数内。因为声明和初始化在编译阶段完成,只涉及代码段和数据段,赋值操作是运行阶段,要放在计算机内存里去“执行”。const-全局|编译-运行|代码数据区|内存区?存疑

总结

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口算法的理解和应用能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值