2022.04.19 21:40 - 22:40
(设计题)LRU 缓存
https://leetcode-cn.com/problems/lru-cache/
- HASH_ITER的使用,从最后开始遍历数组
HASH_ITER(hh, g_usr, cur_usr, next_usr)
-
UT_HASH本身就是一个优秀的双链表实现,可用于快速查找,快速插入
-
HASH_COUNT的使用, 用于统计当前HASH中有多少数据
-
代码实现
typedef struct {
int key;
int value;
UT_hash_handle hh;
} LRUCache;
LRUCache *g_usr = NULL;
int g_size;
LRUCache* lRUCacheCreate(int capacity) {
g_size = capacity;
return g_usr;
}
int lRUCacheGet(LRUCache* obj, int key) {
LRUCache *cur_usr = NULL;
HASH_FIND_INT(g_usr, &key, cur_usr);
if(cur_usr != NULL) {
HASH_DEL(g_usr, cur_usr);
HASH_ADD_INT(g_usr, key, cur_usr);
return cur_usr->value;
}
return -1;
}
void lRUCachePut(LRUCache* obj, int key, int value) {
LRUCache *cur_usr = NULL;
LRUCache *next_usr = NULL;
HASH_FIND_INT(g_usr, &key, cur_usr);
if(cur_usr != NULL) {
HASH_DEL(g_usr, cur_usr);
cur_usr->value = value;
cur_usr->key = key;
HASH_ADD_INT(g_usr, key, cur_usr);
} else {
int cnt = HASH_COUNT(g_usr);
if(cnt == g_size) {
HASH_ITER(hh, g_usr, cur_usr, next_usr) {
HASH_DEL(g_usr, cur_usr);
free(cur_usr);
break;
}
}
LRUCache *new_usr = (LRUCache*)malloc(sizeof(LRUCache));
new_usr->key = key;
new_usr->value = value;
HASH_ADD_INT(g_usr, key, new_usr);
}
return;
}
void lRUCacheFree(LRUCache* obj) {
LRUCache *cur_usr = NULL;
LRUCache *next_usr = NULL;
HASH_ITER(hh, g_usr, cur_usr, next_usr) {
HASH_DEL(g_usr, cur_usr);
free(cur_usr);
}
}
2022.04.19 22:40 - 23:03
(基础题)链表排序
https://leetcode-cn.com/problems/insertion-sort-list/submissions/
https://leetcode-cn.com/problems/sort-list/
- 插入排序的思想:
插入排序的基本思想是,维护一个有序序列,初始时有序序列只有一个元素,每次将一个新的元素插入到有序序列中,将有序序列的长度增加 11,直到全部元素都加入到有序序列中。 - 入参判断
- 链表的插入和恢复
struct ListNode* prev = dummyHead;
while(prev->next->val <= curr->val) {
prev = prev->next;
}
lastSorted->next = curr->next;
curr->next = prev->next;
prev->next = curr;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* insertionSortList(struct ListNode* head)
{
if(head == NULL) {
return head;
}
struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
dummyHead->val = 0;
dummyHead->next = head;
struct ListNode* lastSorted = head;
struct ListNode* curr = head->next;
while(curr != NULL) {
if(lastSorted->val <= curr->val) {
lastSorted = lastSorted -> next;
} else {
struct ListNode* prev = dummyHead;
while(prev->next->val <= curr->val) {
prev = prev->next;
}
lastSorted->next = curr->next;
curr->next = prev->next;
prev->next = curr;
}
curr = lastSorted->next;
}
return dummyHead->next;
}
2022.04.24 22:40~23:29
(基础题) 堆排序 最大平均通过率
https://leetcode-cn.com/problems/maximum-average-pass-ratio/
- 大根堆概念
- 大根堆创建
- 大根堆维护 (增长率作为排序的输入条件)
- 大根堆模板要记住
double calc(int* a)
{
return (double)(a[0] + 1) / (a[1] + 1) - (double)a[0] / a[1];
}
void swap(int **a, int** b) {
int *tmp = *a;
*a = *b;
*b = tmp;
}
void maxHeapify(int **classes, int n, int i)
{
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if(l < n && calc(classes[l]) > calc(classes[largest])) {
largest = l;
}
if(r < n && calc(classes[r]) > calc(classes[largest])) {
largest = r;
}
if( i != largest) {
swap(&classes[i], &classes[largest]);
maxHeapify(classes, n, largest);
}
}
double maxAverageRatio(int** classes, int classesSize, int* classesColSize, int extraStudents)
{
int i;
int n = classesSize;
double aveSum = 0.0;
for(i = n / 2 - 1; i >= 0; i--) {
maxHeapify(classes, n, i);
}
classes[0][0]++;
classes[0][1]++;
for( i = 1; i < extraStudents; i++) {
maxHeapify(classes, classesSize, 0);
classes[0][0]++;
classes[0][1]++;
}
for(i = 0; i < classesSize; i++) {
aveSum += (double)classes[i][0] / (double)classes[i][1];
}
return aveSum / classesSize;
}
#2022.04.30 23:00-23:50
(单调栈)小行星碰撞
https://leetcode-cn.com/problems/XagZNi/
- 单调栈特殊处理
- 正负号判断
bool IsNeedCash(int a, int b)
{
if(((a & ACTIVE) == 0) && ((b & ACTIVE) == ACTIVE)) {
return true;
}
return false;
}
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
#define ACTIVE 0x8000
bool IsNeedCash(int a, int b)
{
if(((a & ACTIVE) == 0) && ((b & ACTIVE) == ACTIVE)) {
return true;
}
return false;
}
int* asteroidCollision(int* asteroids, int asteroidsSize, int* returnSize)
{
int* stack = (int*)malloc(sizeof(int) * asteroidsSize);
memset(stack, 0, sizeof(int) * asteroidsSize);
int top = -1;
for(int i = 0; i < asteroidsSize; i++) {
top += 1;
stack[top] = i;
while(top > 0 && IsNeedCash(asteroids[stack[top - 1]], asteroids[stack[top]])) {
if(abs(asteroids[stack[top - 1]]) == abs(asteroids[stack[top]])) {
top -= 2;
} else {
int tmp = abs(asteroids[stack[top - 1]]) > abs(asteroids[stack[top]]) ? stack[top - 1] : stack[top];
top -= 1;
stack[top] = tmp;
}
}
}
int* res = (int*)malloc(sizeof(int) * (top + 1));
for(int i = 0; i <= top; i++) {
res[i] = asteroids[stack[i]];
}
*returnSize = top + 1;
free(stack);
return res;
}
动态规划 有点像DFS
通过这两个好好研究下DFS
- 礼物的最大价值
https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/
int Max(int a, int b)
{
return a > b ? a : b;
}
#define MAXLEN 201
int dp[MAXLEN][MAXLEN];
int maxValue(int** grid, int gridSize, int* gridColSize)
{
int m = gridSize;
int n = gridColSize[0];
memset(dp, 0, sizeof(int) * MAXLEN * MAXLEN);
dp[0][0] = grid[0][0];
for(int i = 1; i < m; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
for(int j = 1; j < n; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
for(int i = 1; i <m; i++) {
for(int j = 1; j < n; j++) {
dp[i][j] = Max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
- 第K条最小指令
https://leetcode-cn.com/problems/kth-smallest-instructions/
char * kthSmallestPath(int* destination, int destinationSize, int k)
{
int m = destination[0];
int n = destination[1];
int help[m + 1][n + 1];
for(int i = 0; i <=m; i++) {
help[i][0] = 1;
}
for(int i = 0; i <= n; i++) {
help[0][i] = 1;
}
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
help[i][j] = help[i][j - 1] + help[i - 1][j];
}
}
char* res = (char*)malloc(sizeof(char) * (m + n + 1));
int col = m;
int row = n;
for(int i = 0; i < m + n; i++) {
if(row > 0 && k <= help[col][row - 1]) {
res[i] = 'H';
row--;
} else {
if(row > 0) {
k -= help[col][row - 1];
}
res[i] = 'V';
col--;
}
}
res[m + n] = '\0';
return res;
}
双指针特殊题型
https://leetcode-cn.com/problems/find-the-winner-of-an-array-game/
找出数组游戏的赢家
int getWinner(int* arr, int arrSize, int k)
{
int max = arr[0] > arr[1] ? arr[0] : arr[1];
int count = 1;
for(int i = 2; i < arrSize; i++) {
if(count >= k) {
break;
}
if(arr[i] <= max) {
count += 1;
} else{
max = arr[i];
count = 1;
}
}
return max;
}
BFS
单词拆分
https://leetcode-cn.com/problems/word-break/
- 保存可以延申的下标作为入队条件
bool CmpString(char* s1, char* s2, int len)
{
for(int i = 0; i < len; i++) {
if(s1[i] != s2[i]) {
return false;
}
}
return true;
}
bool wordBreak(char * s, char ** wordDict, int wordDictSize)
{
int lens = strlen(s);
int* visited = (int*)malloc(sizeof(int) * (lens + 1));
memset(visited, 0, sizeof(int) * (lens + 1));
int* queryArr = (int*)malloc(sizeof(int) * (lens + 1));
memset(queryArr, 0, sizeof(int) * (lens + 1));
int head = 0;
int tail = 0;
visited[0] = 1;
queryArr[tail] = 0;
tail += 1;
while(head < tail) {
int tmp_index = queryArr[head];
for(int i = 0; i < wordDictSize; i++) {
int tmpLens = strlen(wordDict[i]);
if(tmpLens + tmp_index > lens) {
continue;
}
if(visited[tmp_index + tmpLens] == 1) {
continue;
}
if(CmpString(&s[tmp_index], wordDict[i], tmpLens) == true) {
if(tmpLens + tmp_index == lens) {
return true;
}
queryArr[tail] = tmp_index + tmpLens;
tail += 1;
visited[tmp_index + tmpLens] = 1;
}
}
head += 1;
}
return false;
}
贪心
翻转矩阵后的得分
https://leetcode-cn.com/problems/score-after-flipping-matrix/
1.先将行的第一个全部反转为1
2.再反转列, 数值增大反转 否则不反转
3.不必真的反转,只统计贡献值就可以
int matrixScore(int** grid, int gridSize, int* gridColSize)
{
int row = gridSize;
int col = gridColSize[0];
int ret = row * (1 << (col - 1));
for(int i = 1; i < col; i++) {
int nOnes = 0;
for(int j = 0; j < row; j++) {
if(grid[j][0] == 1) {
nOnes += grid[j][i];
} else {
nOnes += (1 - grid[j][i]);
}
}
int k = nOnes > row - nOnes ? nOnes : row - nOnes;
ret += k * (1 << (col - i - 1));
}
return ret;
}
回溯
2.全部子集
int** ans;
int* ansColSize;
int ansSize;
int* t;
int tSize;
void dfs(int cur, int* nums, int numsSize)
{
if(cur == numsSize) {
// 存结果
int* tmp = (int*)malloc(sizeof(int) * numsSize);
memcpy(tmp, t, sizeof(int) * numsSize);
ans[ansSize] = tmp;
ansColSize[ansSize] = tSize;
ansSize +=1;
return;
}
t[tSize++] = nums[cur];
dfs(cur + 1, nums, numsSize);
tSize -= 1;
dfs(cur + 1, nums, numsSize);
}
int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
ans = (int**)malloc(sizeof(int*) * (1 << numsSize));
ansColSize = (int*)malloc(sizeof(int) * (1 << numsSize));
t = (int*)malloc(sizeof(int) * numsSize);
ansSize = 0;
tSize = 0;
dfs(0, nums, numsSize);
* returnSize = 1 << numsSize;
*returnColumnSizes = ansColSize;
return ans;
}
1.全排列
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** ans;
int* ansCol;
int ansSize;
int* path;
int g_used[1000] = {0};
void dfs(int cur, int* nums, int numsSize)
{
if(cur == numsSize) {
int* tmpx = (int*)malloc(sizeof(int) * numsSize);
memcpy(tmpx, path, sizeof(int) * numsSize);
ans[ansSize] = tmpx;
ansCol[ansSize] = numsSize;
ansSize += 1;
return;
}
for(int i = 0; i < numsSize; i++) {
if(g_used[i] == 1) {
continue;
}
path[cur] = nums[i];
g_used[i] = 1;
dfs(cur + 1, nums, numsSize);
g_used[i] = 0;
}
}
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
memset(g_used, 0, sizeof(g_used));
ans = (int**)malloc(sizeof(int*) * (100000));
ansCol = (int*)malloc(sizeof(int)* (100000));
path = (int*)malloc(sizeof(int)* (numsSize));
ansSize = 0;
dfs(0, nums, numsSize);
*returnSize = ansSize;
*returnColumnSizes = ansCol;
return ans;
}