力扣题目总结

力扣题目总结

  1. 135.分发糖果:

    //根据规则只需要满足每个人至少有一个糖果,且前一个的评分如果比后一个高就需要它的糖果更多;但是只有一遍的话会出现bug,因为每次对比可能会使自身糖果数发生改变从而导致前一个的糖果数不准确,此时我们需要从后往前再来一遍再进行一次遍历修正。
    int candy(int* ratings, int ratingsSize){
        int a[ratingsSize];
        int i,j,cnt = 0;
        for(i=0;i<ratingsSize;i++){//初始化
            a[i]=1;
        }
        for(i=0;i<ratingsSize-1;i++){//前往后
            if(ratings[i]>ratings[i+1]){
                while(a[i]<=a[i+1]){
                    a[i]++;
                }
            }
            if(ratings[i]<ratings[i+1]){
                while(a[i]>=a[i+1]){
                    a[i+1]++;
                }
            }
        }
        for(i=ratingsSize-1;i>0;i--){//后往前
            if(ratings[i]>ratings[i-1]){
                while(a[i]<=a[i-1]){
                    a[i]++;
                }
            }
            if(ratings[i]<ratings[i-1]){
                while(a[i]>=a[i-1]){
                    a[i-1]++;
                }
            }
            cnt += a[i];
        }
        if(ratingsSize>0){
            cnt += a[0];
        }
        return cnt;
    }
    
  2. 85.最大矩形:

int maximalRectangle(char** matrix, int matrixSize, int* matrixColSize){
    int m = matrixSize;//行
    if(m==0){
        return 0;//如果是0大小就返回0
    }
    int n = matrixColSize[0];//列
    int ll[m][n];//储存原数组每个元素左边有多少1的数组
    memset(ll,0,sizeof(ll));//清空
    int i,j;
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            if(matrix[i][j]=='1'){
                ll[i][j]=((j==0)?0:ll[i][j-1])+1;//如果是最外圈就填充1,否则就加上左边存的数字。
            }
        }
    }
    //初始宽已经定义完了
    int ret = 0;
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            if(matrix[i][j]=='0'){
                continue;//如果该点是0就下一个点
            }
            int width = ll[i][j];//宽,向左的距离
            int area = width;//先和宽相同,高为1
            int k;
            for(k=i-1;k>=0;k--){//向上推进
                width = fmin(width,ll[k][j]);//逐渐缩小宽度,因为要长乘宽
                area = fmax(area,(i-k+1)*width);//每次都计算下最大面积
            }
            ret = fmax(ret,area);//计算所有可能的最大面积
        }
    }
    return ret;
}
  1. 330.按要求补齐数组:

    /*可以这么理解,以[1,5,10]的例子为例: 我们从1开始遍历,并且维护一个指向nums的下标.一开始是1,而我们看到当前nums数组的第一个元素就是1,所以不需要其他操作.直接跳到2,并且让pos指向nums的第二个元素;
    
    现在,我们的目标数是2,但是当前pos指向的数却是5,显然我们只能自己填充一个2,所以让res+1;既然我们已经填过2了,而在2之前可以被覆盖的最长区间长度是1,所以当前可以遍历到的最大区间长度变成了3(即2 + 1);
    
    然后,我们可以忽略3,直接跳到4(因为上一步已经知道3在最大覆盖范围内了)。我们发现4同样比当前pos所指向的nums元素小,所以我们得填入4,即让res+1;既然已经填入4了,而我们知道在4之前可以覆盖的连续区间是(1-3),所以当前可以覆盖的最大区间被扩展到了7(即4 + 3)。
    
    接下来我们可以直接跳过5、6、7来到8,而当前pos所指向的元素是5,所以当前可覆盖的区间大小又可以加上5了(7+5 = 12),并让pos指向下一个元素
    
    最后我们跳过了7-12,从13开始遍历,这时候pos所指的元素是10,所以覆盖范围变成了12 + 10 = 22 >20,说明可以完全覆盖指定区间了!
    
    到这里大概能够看出端倪 :我们不断维持一个从1开始的可以被完全覆盖的区间,举个例子,当前可以完全覆盖区间是[1,k],而当前pos所指向的nums中的元素为B,说明在B之前(因为是升序,所以都比B小)的所有元素之和可以映射到1-----k,而当我们把B也加入进去后,显然,可映射范围一定向右扩展了B个,也就是变成了1---k+B,这就是解题的思路*/
    
    int minPatches(int* nums, int numsSize, int n){
        long long i,k=-1,cnt=0;
        long ret = 0;//数字范围
        for(i = 1;i <= n;i++){//遍历1 - n
            if(k == numsSize-1 || nums[k+1] > i){//如果到达数组最后一个数或者数组下一个数比此时的i大就添加一个数(此时的i);
                ret += i;//范围扩大
                cnt++;//计数加一
            }else{//单纯是范围没加够就给它加够,然后让i直接跳到最大范围处;
                ret += nums[k+1];
                k++;
            }
            i = ret;
        }
        return cnt;
    }
    //借用一下评论区大佬的思路
    
  2. 1046.最后一块石头的重量:

    //用了哈希表来装这些数据
    int lastStoneWeight(int* stones, int stonesSize){
        int book[1100] = {0};
        int i,j;
        int min=1100,max=0;
        for(i=0;i<stonesSize;i++){
            book[stones[i]]++;
            if(max < stones[i]){
                max = stones[i];//最大的数
            }
            if(min > stones[i]){
                min = stones[i];//最小的数
            }
        }//为了少遍历一些
        for(i = max;i >= min;i--){
            if(book[i] == 0){//如果没有这个数就跳过
                continue;
            }
            while(book[i] >= 2){//如果这个数有两个以上就删除两个然后要将最小值确定为0,避免:[2,2]这种情况;
                book[i] -= 2;
                min = 0;
            }
            if(book[i] == 1 && i > min){//如果这个数不是最小的而且只有一个,就向前找
                for(j = i-1;j >= min && book[j] == 0;j--);//找到了前面那个数,或者超出范围了,没找到
                if(j == min-1){//如果前面没有数了就直接返回此时的数
                    return i;
                }
                if(i-j < min){//如果出现比最初小的数了,就更新最小值
                    min = i-j;
                }
                book[i] = 0;//减掉此时的数
                book[j] -= 1;//减少一个前面的数
                book[i-j]++;//增加一个新数
            }
        }
        return i+1;
    }
    
  3. 435.无重叠区间:

    void Qs(int a[][2],int low,int high)//快排
    {
        int i=low;
        int j=high;
        if(low>=high){
    	    return;
        }
        int key1=a[low][0];
        int key2=a[low][1];
        while(low<high){
            for(;low<high && key1 <= a[high][0];high--);
            if(key1 > a[high][0]){  //
                a[low][1]=a[high][1];
                a[low][0]=a[high][0];
            }
            for(;low<high && key1 >= a[low][0];low++);
            if(key1<a[low][0]){  //找到了 
                a[high][1]=a[low][1];
                a[high][0]=a[low][0];
            }
        }
    	a[low][0]=key1;
        a[low][1]=key2;
    	Qs(a,i,low-1);
    	Qs(a,low+1,j);
    }
    int min(int x,int y)
    {
        if(x<y){
            return x;
        }else{
            return y;
        }
    }
    int eraseOverlapIntervals(int** intervals, int intervalsSize, int* intervalsColSize){
        if(intervalsSize<=1){
            return 0;
        }
        int i,j;
        int a[intervalsSize][2]=intervals;
        Qs(a,0,intervalsSize-1);//按照左边界进行排序
        int cnt=0;
        j = a[0][1];//初始化判断点为第一个点的右边界
        for(i=1;i<intervalsSize;i++){
            if(j>a[i][0]){//如果遇到冲突了,就减去一个区间,保留右边界小的那个
                ++cnt;
                j = min(j,a[i][1]);
            }else{
                j = a[i][1];//更新判断点
            }
        }
        return cnt;
    }
    
  4. 86.分割链表:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    
    //大的放一起,小的放一起,然后分别进行遍历
    struct ListNode* partition(struct ListNode* head, int x){
        struct ListNode *head_max = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode *head_min = (struct ListNode*)malloc(sizeof(struct ListNode));
        head_max->next = head_min->next = NULL;
        struct ListNode *q_max = head_max,*q_min = head_min;
        struct ListNode *p = head;
        while(p){
            struct ListNode *q = (struct ListNode*)malloc(sizeof(struct ListNode));
            q->val = p->val;
            q->next = NULL;
            if(q->val<x){
                q_min->next = q;
                q_min = q;
            }else{
                q_max->next = q;
                q_max = q;
            }
            p = p->next;
        }
        p = head;
        q_min = head_min->next;
        q_max = head_max->next;
        while(q_min){
            p->val = q_min->val;
            p = p->next;
            q_min = q_min->next;
        }
        while(q_max){
            p->val = q_max->val;
            p = p->next;
            q_max = q_max->next;
        }
        return head;
    }
    

以上是最近力扣每日一题的部分总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值