滑动窗口最大值
-
单调队列:单调递增或单调递减
-
deque可以两边扩增(用数组实现)
-
解题思路
- 用单调递减队列只维护可能是滑动窗口最大值的数
- 队列出口元素是滑动窗口最大值
- pop:如果窗口移除的元素等于队列的最大值,队列弹出元素,否则不做操作
- push:如果push的元素大于队列入口的数值,那么将队列入口的元素弹出,直到push的元素小于等于入口元素的数值为止
/**
* 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个高频元素
- 解题思路
- 要统计元素出现频率——哈希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-全局|编译-运行|代码数据区|内存区?存疑