《七月集训》第八日——前缀和

前言

这是七月集训的第八日,今日的训练内容是 前缀和

解题报告

1.力扣1894

原题链接

1894. 找到需要补充粉笔的学生编号

题目概述

一个班级里有 n 个学生,编号为 0 到 n - 1 。每个学生会依次回答问题,编号为 0 的学生先回答,然后是编号为 1 的学生,以此类推,直到编号为 n - 1 的学生,然后老师会重复这个过程,重新从编号为 0 的学生开始回答问题。

给你一个长度为 n 且下标从 0 开始的整数数组 chalk 和一个整数 k 。一开始粉笔盒里总共有 k 支粉笔。当编号为 i 的学生回答问题时,他会消耗 chalk[i] 支粉笔。如果剩余粉笔数量 严格小于 chalk[i] ,那么学生 i 需要 补充 粉笔。

请你返回需要 补充 粉笔的学生 编号 。

解题思路

首先先将所有的粉笔消耗量全都加起来,然后用 k 对粉笔的消耗量进行取模运算,这样就可以使得在 k 的值一定会小于一次循环的最大消耗量,此时再对消耗量进行累加,什么时候的消耗量大于了现在的 k 就返回现在的下标 i 即可。

源码剖析

int chalkReplacer(int* chalk, int chalkSize, int k){
    long sum=0;
    int i;
    for(i=0;i<chalkSize;++i){
        sum+=chalk[i];
    }
    k%=sum;
    sum = 0;
    for(i=0;i<chalkSize;i++){
        sum+=chalk[i];
        if(sum>k){
            break;
        }
    }
    return i;
}

2.力扣2256

原题链接

2256. 最小平均差

题目概述

给你一个下标从 0 开始长度为 n 的整数数组 nums 。

下标 i 处的 平均差 指的是 nums 中 前 i + 1 个元素平均值和 后 n - i - 1 个元素平均值的 绝对差 。两个平均值都需要 向下取整 到最近的整数。

请你返回产生 最小平均差 的下标。如果有多个下标最小平均差相等,请你返回 最小 的一个下标。

注意:

  • 两个数的 绝对差 是两者差的绝对值。
  • n 个元素的平均值是 n 个元素之 和 除以(整数除法) n 。
  • 0 个元素的平均值视为 0 。

解题思路

我觉得这应该算是一道模拟的题目,首先用前缀和数组记录下前缀和,然后开始按照题目要求来遍历前缀和数组,注意特别处理一下某些特殊情况和循环的边界,总的来说,这个地方还是有点不清不楚的,虽然多试错几次可以写出来,但是边界条件相当的不熟练,还需多练。

源码剖析

int minimumAverageDifference(int* nums, int numsSize){
    long* presum=(long*)malloc(sizeof(long)*(numsSize+1));
    memset(presum,0,sizeof(presum));
    int i;
    presum[0]=0;
    for(i=1;i<numsSize+1;++i){
        presum[i]=nums[i-1]+presum[i-1];
    }
    int min = INT_MAX;
    int ans = 0;
    for(i=0;i<numsSize;++i){
        if((numsSize-i-1)!=0){
            int tmp = abs((presum[i+1]/(i+1))-(presum[numsSize]-presum[i+1])/(numsSize-i-1));
            if(tmp<min){
                min = tmp;
                ans = i;
            }
        }else{
            int tmp = abs(presum[i+1]/(i+1));
            if(tmp <min){
                min = tmp;
                ans = i;
            }
        }
    }
    return ans;
}

3.力扣1737

原题链接

1737. 满足三条件之一需改变的最少字符数

题目概述

给你两个字符串 a 和 b ,二者均由小写字母组成。一步操作中,你可以将 a 或 b 中的 任一字符 改变为 任一小写字母 。

操作的最终目标是满足下列三个条件 之一 :

  • a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母 。
  • b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母 。
  • a 和 b 都 由 同一个 字母组成。

返回达成目标所需的 最少 操作数。

解题思路

函数分为两个部分,一个部分用来计算前两种情况的最小操作数,一个用来计算最后一种的。

首先说说后者,首先将所有字母出现次数都填入哈希表,然后遍历哈希表,找到出现了最多次数的字母,然后用所有字母的总数减去出现次数最多的字母个数,就得到了最少的改变次数。

再说说前者,虽然是两种情况,但其实只要修改一下传入参数就可以反过来寻找,因此来说一说这里的实现思路:使用暴力的枚举法,枚举 26 个字母,将 a 串的所有字符都小于等于这个字母的数(需改变数)与 b 串所有字符都大于等于这个字母的数(需改变数)并加和。枚举完所有字母后,自然就直接可以得到,使得 a 中的字符全都严格大于 b 中字母。然后交换传入参数,就可以得到另一种情况的最少操作数。

最后取 3 种情况中最小的数即可,总的来说,这题的思路是暴力枚举。

源码剖析

int change(char *a,char *b,int asize,int bsize){
    int ans = INT_MAX;
    for(char x = 'a';x<'z';++x){
        int sum = 0;
        for(int i = 0;i<asize;++i){
            sum += (a[i]<=x?0:1);
        }
        for(int i = 0;i<bsize;++i){
            sum += (b[i]>x?0:1);
        }
        ans = ans<sum?ans:sum;
    }
    return ans;
}

int minmend(char *a,char *b,int asize,int bsize){
    int hash[26]={0};
    int i;
    int max = 0;
    for(i = 0;i<asize;++i){
        hash[(a[i]-'a')]++;
    }
    for(i = 0;i<bsize;++i){
        hash[(b[i]-'a')]++;
    }
    for(i = 0;i<26;++i){
        max = max>hash[i]?max:hash[i];
    }
    return asize+bsize-max;
}

int minCharacters(char * a, char * b){
    int asize = strlen(a);
    int bsize = strlen(b);
    int tmp = change(a,b,asize,bsize)<change(b,a,bsize,asize)?change(a,b,asize,bsize):change(b,a,bsize,asize);
    return tmp<minmend(a,b,asize,bsize)?tmp:minmend(a,b,asize,bsize);
}

4.力扣2055

原题链接

2055. 蜡烛之间的盘子

题目概述

给你一个长桌子,桌子上盘子和蜡烛排成一列。给你一个下标从 0 开始的字符串 s ,它只包含字符 ‘’ 和 ‘|’ ,其中 '’ 表示一个 盘子 ,‘|’ 表示一支 蜡烛 。

同时给你一个下标从 0 开始的二维整数数组 queries ,其中 queries[i] = [lefti, righti] 表示 子字符串 s[lefti…righti] (包含左右端点的字符)。对于每个查询,你需要找到 子字符串中 在 两支蜡烛之间 的盘子的 数目 。如果一个盘子在 子字符串中 左边和右边 都 至少有一支蜡烛,那么这个盘子满足在 两支蜡烛之间 。

比方说,s = “|||||" ,查询 [3, 8] ,表示的是子字符串 "||**|” 。子字符串中在两支蜡烛之间的盘子数目为 2 ,子字符串中右边两个盘子在它们左边和右边 都 至少有一支蜡烛。
请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。

解题思路

先做记录。

源码剖析


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值