Leetcode刷题记录

Leetcode805数组的均值分割

Leetcode刷题记录_第1张图片

Leetcode刷题记录_第2张图片
Leetcode刷题记录_第3张图片
设n个数被分成了两组,一组k个数,另一组n-k个数
假设这k个数的平均值是数组的平均值average,那么另一组n-k个数的平均值也必定为average
证明:
假设n-k个数的平均值不是average, 由于在n-k个数的平均值等于average时,我们可以很容易的算出这个数组的平均值是,average,若这n-k个数组的平均值 > average,我们用这个数组和n个数的数组合一起算出来的平均值是大于average的
所以,只要我们确定了k个数的平均值是average,剩下n-k个数的平均值也必定是average,因此就转换成了01背包问题,并且我们会划分成两个子集,那么肯定有一个子集中元素的个数 <= n/2

Leetcode293滑动窗口的最大值

Leetcode刷题记录_第4张图片
Leetcode刷题记录_第5张图片

方法一(堆)

//手写堆超时,37/51
struct Node{
    int num,pos; //记录每个点的值和在数组中的下标
}heap[100010];
int cnt; //堆的大小
void down(int x)
{
    int tt = x;
    if(2*x <= cnt && heap[tt].num < heap[2*x].num) tt = 2 * x;
    if(2*x+1<=cnt && heap[tt].num < heap[2*x+1].num) tt = 2 * x + 1;
    if(tt != x)
    {
        int temp_num = heap[tt].num, temp_pos = heap[tt].pos;
        heap[tt].num = heap[x].num;
        heap[tt].pos = heap[x].pos;
        heap[x].num = temp_num;
        heap[x].pos = temp_pos;
        down(tt);
    }
}

int* maxSlidingWindow(int* nums, int n, int k, int* returnSize){
    int* res = malloc(sizeof(int)*n);
    int len = 0;
    cnt = 0;
    for(int i = 0; i < k; i++){
        heap[++cnt].num = nums[i];
        heap[cnt].pos = i;
    }
    for(int i = cnt/2;i;i--) down(i);
    res[len++] = heap[1].num;
    for(int i = k; i < n; i++){
        int start = i - k + 1;
        heap[++cnt].num = nums[i];
        heap[cnt].pos = i;
        for(int z = cnt; z; z--) down(z);
        while(heap[1].pos < start)
        {
            heap[1].num = heap[cnt].num;
            heap[1].pos = heap[cnt].pos;
            for(int z = cnt;z;z--) down(z);
        }
        res[len++] = heap[1].num;
    }
    *returnSize = len;
    return res;
}

方法二:单调队列

Leetcode刷题记录_第6张图片
Leetcode刷题记录_第7张图片

#include 
#include 
#include 
#define N (int)(1e6+10)
int n,k;
int q[N],nums[N];

int main()
{
    scanf("%d%d",&n,&k);
    for(int i = 0; i < n; i++) scanf("%d",&nums[i]);
    int front = 0, tail = -1; //注意队列queue中记录的是下表,并且是窗口内的下标
    //我们始终保持队头元素是答案,求最大值就是单调递减的队列,求最小值就是单调递增的队列
    for(int i = 0; i < n; i++){
        int start = i - k + 1;
        while(front <= tail && q[front] < start) front++;
        while(front <= tail && nums[q[tail]] > nums[i]) tail--;
        q[++tail] = i;
        if(start >= 0) printf("%d ",nums[q[front]]);
    }
    printf("\n");
    front = 0, tail = -1;
    for(int i = 0; i < n; i++){
        int start = i - k + 1;
        while(front <= tail && q[front] < start) front++; //如果有元素不在窗口内就弹出
        while(front <= tail && nums[q[tail]] < nums[i]) tail--; //那些比这个数更小的数都不可能被使用了
        q[++tail] = i;
        if(start >= 0) printf("%d ",nums[q[front]]);
    }
    return 0;
}

Leetcode1703得到连续 K 个 1 的最少相邻交换次数

Leetcode刷题记录_第8张图片
题解解释

Leetcode347前k个高频元素

Leetcode刷题记录_第9张图片

struct Node{
    int num,val; //数字和数字出现的次数
}nodes[100010];

int cmp(const void* a,const void* b)  //数组从小到大排序
{
    return *(int*)a - *(int*)b;
}

int cmp2(const void* a,const void* b) //结果结构体从大到小排序
{
    struct Node* aa = (struct Node*)a;
    struct Node* bb = (struct Node*)b;
    if(aa->val < bb->val) return 1;
    return -1;
}

int* topKFrequent(int* nums, int numsSize, int k, int* returnSize){
    *returnSize = k;
    int n = numsSize;
    int* res = malloc(sizeof(int)*n);
    qsort(nums,n,sizeof(nums[0]),cmp);
    int cnt = 0;
    nodes[cnt].num = nums[0];
    nodes[cnt].val = 1;
    for(int i = 1; i < n; i++){
        if(nums[i] == nums[i-1]){
            nodes[cnt].val++;
        }
        else{
            nodes[++cnt].num = nums[i];
            nodes[cnt].val = 1;
        }
    }
    qsort(nodes,cnt+1,sizeof(nodes[0]),cmp2);
    for(int i = 0; i < k; i++) res[i] = nodes[i].num;
    return res;
}

Leetcode490迷宫I

Leetcode刷题记录_第10张图片
注意这个题是得能够停在这个点,不仅仅是能够经过这个点就可以的

struct Node{
    int x,y;
};
int dx[4] = {1,-1,0,0},dy[4] = {0,0,1,-1};
bool hasPath(int** maze, int mazeSize, int* mazeColSize, int* start, int startSize, int* destination, int destinationSize){
    int n = mazeSize, m = *mazeColSize;
    bool visit[1010][1010];
    memset(visit,0,sizeof(visit));
    struct Node queue[10010];
    memset(queue,0,sizeof(queue));
    int front = 0 ,tail = -1;
    queue[++tail].x = start[0];
    queue[tail].y = start[1];
    visit[start[0]][start[1]] = true;
    while(front <= tail)//队列记录那些被访问过墙边界上的节点
    {
        struct Node node = queue[front++];
        if(node.x == destination[0] && node.y == destination[1]) return true;
        for(int i = 0; i < 4; i++)
        {
            int nx = node.x + dx[i];
            int ny = node.y + dy[i];
            while(nx >= 0 && nx < n && ny >= 0 && ny < m && maze[nx][ny] != 1)
            {
                nx += dx[i],ny += dy[i];
            }
            nx -= dx[i], ny -= dy[i];
            if(!visit[nx][ny]){
                visit[nx][ny] = true;
                tail++;
                queue[tail].x = nx;
                queue[tail].y = ny;
            }
        }
    }
    if(visit[destination[0]][destination[1]]) return true;
    return false;
}

Leetcode505迷宫II

Leetcode刷题记录_第11张图片

struct Node{
    int x,y;
};
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int shortestDistance(int** maze, int mazeSize, int* mazeColSize, int* start, int startSize, int* destination, int destinationSize){
    int n = mazeSize, m = *mazeColSize;
    int dis[n+10][m+10];
    memset(dis,0x3f,sizeof(dis));
    dis[start[0]][start[1]] = 0;
    struct Node queue[10010];
    int front = 0, tail = -1;
    queue[++tail].x = start[0];
    queue[tail].y = start[1];
    while(front <= tail)
    {
        struct Node node = queue[front++];
        for(int i = 0; i < 4; i++)
        {
            int nx = node.x + dx[i];
            int ny = node.y + dy[i];
            int step = 1;
            while(nx >= 0 && nx < n && ny >= 0 && ny < m && maze[nx][ny] != 1){
                nx = nx + dx[i],ny = ny + dy[i];
                step++;
            }
            nx -= dx[i], ny -= dy[i], step--;
            if(dis[nx][ny] > dis[node.x][node.y] + step){
                dis[nx][ny] = dis[node.x][node.y] + step;
                queue[++tail].x = nx;
                queue[tail].y = ny;
            }
            while(nx != node.x && ny != node.y){
                dis[nx][ny] = fmin(dis[nx][ny],dis[node.x][node.y]+step);
                nx -= dx[i],ny -= dy[i];
                step--;
            }
        }
    }
    if(dis[destination[0]][destination[1]] > 0x3f3f3f3f/2) return -1;
    return dis[destination[0]][destination[1]];
}

Leetcode1962迷宫中的最短出口

Leetcode刷题记录_第12张图片

struct Node{
    int x,y;
};
int visit[110][110];
int dx[4] = {1,-1,0,0},dy[4] = {0,0,1,-1};
int nearestExit(char** maze, int mazeSize, int* mazeColSize, int* entrance, int entranceSize){
    int n = mazeSize, m = *mazeColSize;
    int dis[110][110];
    memset(visit,0,sizeof(visit));
    memset(dis,0x3f,sizeof(dis));
    dis[entrance[0]][entrance[1]] = 0;
    struct Node queue[10010];
    int front = 0, tail = -1;
    queue[++tail].x = entrance[0];
    queue[tail].y = entrance[1];
    while(front <= tail)
    {
        struct Node node = queue[front++];
        for(int i = 0; i < 4; i++){
            int nx = node.x + dx[i];
            int ny = node.y + dy[i];
            if(nx < 0 || nx >= n | ny < 0 || ny >= m || maze[nx][ny] == '+' ||visit[nx][ny]) continue;
            dis[nx][ny] = dis[node.x][node.y] + 1;
            visit[nx][ny] = true;
            queue[++tail].x = nx;
            queue[tail].y = ny;
            
        }
    }  
    int res = 0x3f3f3f3f;
    for(int i = 0; i < n; i++){
        int x = i, y = 0;
        if(x == entrance[0] && y == entrance[1]) continue;
        res = fmin(res,dis[x][y]);
    }
    for(int i = 0; i < m; i++)
    {
        int x = 0, y = i;
        if(x == entrance[0] && y == entrance[1]) continue;
        res = fmin(res,dis[x][y]);
    }
    for(int i = 0; i < n; i++){
        int x = i, y = m-1;
        if(x == entrance[0] && y == entrance[1]) continue;
        res = fmin(res,dis[x][y]);
    }
    for(int i = 0; i < m; i++){
        int x = n-1,y = i;
        if(x == entrance[0] && y == entrance[1]) continue;
        res = fmin(res,dis[x][y]);
    }
    if(res > 0x3f3f3f3f / 2) return -1;
    return res;
}

Leetcodet988

Leetcode刷题记录_第13张图片
这个题要给字符串进行字典序排序
Leetcode刷题记录_第14张图片

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
void reverse(char* s)
{
    int n = strlen(s);
    int l = 0, r = n - 1;
    while(l < r)
    {
        char temp = s[l];
        s[l] = s[r];
        s[r] = temp;
        l++,r--;
    }
}

char hash[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
struct Node{
    char tmp[10010];
}nodes[10010];
int pos;

int cmp(const void* a, const void* b)
{
    struct Node* aa = (struct Node*)a;
    struct Node* bb = (struct Node*)b;
    if(strcmp(aa->tmp,bb->tmp) > 0) return 1;
    return -1;
}

void dfs(struct TreeNode* root,char* path,int cnt)
{
    if(root->left == NULL && root->right == NULL)
    {
        path[cnt++] = hash[root->val];
        for(int i = 0; i < cnt; i++) nodes[pos].tmp[i] = path[i];
        nodes[pos].tmp[cnt] = '\0';
        pos++;
        return;
    }
    path[cnt++] = hash[root->val];
    if(root->left) dfs(root->left,path,cnt);
    if(root->right) dfs(root->right,path,cnt);
}

char * smallestFromLeaf(struct TreeNode* root){
    char* path = malloc(sizeof(char)*10010);
    int cnt = 0;
    pos = 0;
    dfs(root,path,cnt);
    for(int i = 0; i < pos; i++) reverse(nodes[i].tmp);
    for(int i = 0; i < pos; i++) printf("%s\n",nodes[i].tmp);
    qsort(nodes,pos,sizeof(nodes[0]),cmp);
    return nodes[0].tmp;
}

Leetcode386字典序排数

Leetcode刷题记录_第15张图片
直接转成字符串,然后用strcmp和qsort排序即可

void reverse(char* s,int l,int r)
{
    while(l < r)
    {
        char temp;
        temp = s[l];
        s[l] = s[r];
        s[r] = temp;
        l++,r--;
    }
}
int cmp(const void* a,const void* b)
{
    int* aa = (int*)a;
    int* bb = (int*)b;
    int num1 = *aa, num2 = *bb;
    char* ans1 = malloc(sizeof(char)*20);
    char* ans2 = malloc(sizeof(char)*20);
    int cnt1 = 0, cnt2 = 0;
    while(num1)
    {
        ans1[cnt1++] = num1 % 10 + '0';
        num1 /= 10;
    }
    ans1[cnt1] = '\0';
    while(num2)
    {
        ans2[cnt2++] = num2 % 10 + '0';
        num2 /= 10;
    }
    ans2[cnt2] = '\0';
    reverse(ans1,0,cnt1-1);
    reverse(ans2,0,cnt2-1);
    if(strcmp(ans1,ans2) > 0) return 1;
    return -1;
}

int* lexicalOrder(int n, int* returnSize){
    int* res = malloc(sizeof(int)*(n+10));
    for(int i = 0; i < n; i++) res[i] = i+1;
    *returnSize = n;
    qsort(res,n,sizeof(res[0]),cmp);
    return res;
}

Leetcode149直线上点最多的数目

Leetcode刷题记录_第16张图片
Leetcode刷题记录_第17张图片
Leetcode刷题记录_第18张图片

struct Node{
    int x,y;
}nodes[1010];
int maxPoints(int** points, int pointsSize, int* pointsColSize){
    int n = pointsSize;
    for(int i = 0; i < n; i++){
        nodes[i].x = points[i][0];
        nodes[i].y = points[i][1];
    }
    if(n == 1) return 1;
    if(n == 2) return 2;
    int res = 2;
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++){
            int ans = 2;
            int x1 = nodes[i].x, y1 = nodes[i].y;
            int x2 = nodes[j].x, y2 = nodes[j].y;
            int dx = x1 - x2, dy = y1 - y2;
            for(int k = 0; k < n; k++){
                if(k == i || k == j) continue;
                if(dy * (nodes[k].x - x2) == dx * (nodes[k].y - y2)) ans++;
            }
            res = fmax(res,ans);
        }
    }
    return res;
}

Leetcode1631最小体力消耗路径

Leetcode刷题记录_第19张图片
Leetcode刷题记录_第20张图片
这个题求的是一条路径上,最大值与最小值的差值

方法一:二分法

Leetcode刷题记录_第21张图片

struct Node{
    int x,y;
};
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};

//能否再找到一条路径使得连续的两个点差值的最大值不超过x
bool check(int** heights,int n,int m,int x)
{
    bool visit[n+1][m+1]; //(i,j) --> i*n+j这个点能否有一条路径相邻节点差值最大值不超过x的路径到这个点
    memset(visit,0,sizeof(visit));
    struct Node queue[100010];
    int front = 0, tail = -1;
    visit[0][0] = 1;
    queue[++tail].x = 0,queue[tail].y = 0;
    while(front <= tail)
    {
        struct Node node = queue[front++];
        for(int i = 0; i < 4; i++){
            int nx = node.x + dx[i];
            int ny = node.y + dy[i];
            if(nx>=0 && nx < n && ny >= 0 && ny < m && !visit[nx][ny] && abs(heights[nx][ny]-heights[node.x][node.y]) <= x){
                visit[nx][ny] = true;
                queue[++tail].x = nx;
                queue[tail].y = ny;
            }
        }
    }
    if(visit[n-1][m-1]) return true;
    return false;
}

int minimumEffortPath(int** heights, int heightsSize, int* heightsColSize){
    int n = heightsSize, m = *heightsColSize;
    int l = 0, r = 10000010;
    while(l < r)
    {
        int mid = (l + r) / 2;
        if(check(heights,n,m,mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

方法二:最短路

而这道题本质上是一道最短路问题,我们把每个格子抽象成一个节点
Leetcode刷题记录_第22张图片
Leetcode刷题记录_第23张图片

你可能感兴趣的:(算法,leetcode,算法,数据结构)