7月算法训练------第八天(前缀和)解题报告

7月算法训练------第八天(前缀和)解题报告

题目类型:前缀和
题目难度:中等

第一题、1894. 找到需要补充粉笔的学生编号

  1. 题目链接:1894. 找到需要补充粉笔的学生编号
  2. 思路分析:
    先将数组chalk中的数全加起来得到sum,用sum对k取余y,得到余数y,然后用y减去数组chalk中的每个数,当结果小于0时,就返回当前索引;
  3. 代码:
class Solution {
    public int chalkReplacer(int[] chalk, int k) {
        long sum = 0;
        for(int i : chalk){
            sum += (long)i;
        }
        long y = k % sum;
        if(y == 0){
            return 0;
        }
        long x = y;
        for(int i = 0;i < chalk.length; i++){
            x = x - (long)chalk[i];
            if(x < 0){
                return i;
            }
        }
        return 0;
    }
}

第二题、2256. 最小平均差

  1. 题目链接:2256. 最小平均差
  2. 思路分析:
    我们用两个数组存储前i个和后n-i个数的和,即frontSumbackSum
    然后,我们求的前i个和后n-i个数的平均值,即frontMeanbackMean
    用数组sub记录他们之间的差值的绝对值,遍历sub得到其中最小值和最小值的索引,返回这个索引。
  3. 代码:
class Solution {
    public int minimumAverageDifference(int[] nums) {
        if(nums.length == 1) return 0;
        int n = nums.length;
        long[] frontSum = new long[n];
        long[] backSum = new long[n];
        frontSum[0] = (long)nums[0];
        for(int i = 1; i < n; i++){
            frontSum[i] = frontSum[i-1] + (long)nums[i];
        }
        backSum[n - 1] = 0;
        backSum[n - 2] = (long)nums[n - 1];
        for(int j = n- 3; j >= 0; j--){
            backSum[j] = backSum[j+1] + (long)nums[j+1];
        }
        long[] frontMean = new long[n];
        long[] backMean = new long[n];
        for(int i = 0; i < n; i++){
            frontMean[i] = frontSum[i] / (i + 1);
            if(i == n - 1){
                backMean[i] = 0;
            }else{
                backMean[i] = backSum[i] / (n - 1 - i);
            }
        }
        long[] sub = new long[n];
        for(int i = 0; i < n; i++){
            sub[i] = Math.abs(frontMean[i] - backMean[i]);
        }
        long min = Long.MAX_VALUE;
        for(int i = 0; i < n; i++){
            if(sub[i] < min){
                min = sub[i];
            }
        }
        for(int i = 0; i < n; i++){
            if(sub[i] == min){
                return i;
            }
        }
        return 1;
    }
}

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

  1. 题目链接:1737. 满足三条件之一需改变的最少字符数
  2. 思路分析:
    我们用minChar(char[] a, char[] b)方法计算满足条件一和条件二的最小值;
    minChar(char[] a, char[] b)的思路就是:
    我们枚举26个小写字母,如果a中有大于当前枚举字母的字母,就将sum++
    如果b中有小于当前枚举字母的字母,也让sum++
    当两个字符串都遍历完之后,更新最小值;
    用这种方法,将26个字母都枚举过后,最终的最小值就可以返回了。
int min =  Math.min(minChar(arra, arrb), minChar(arrb, arra));

对于代码中的这个minChar(arra, arrb),求得满足条件一的最小值;
minChar(arrb, arra),求得满足条件二的最小值。
最终将这两个值取最小,就得到条件一和条件二的最小值;

而对于条件三:我们也采用类似的方法,枚举26个字母,记录两个字符串中与枚举字母不相等的字符数量,返回最小值;
将以上两个最小值,再求一次最小,就是结果了。
3. 代码:

class Solution {
    public int minCharacters(String a, String b) {
        // if(a.equals(b)){
        //     return 0;
        // }
        char[] arra = a.toCharArray();
        char[] arrb = b.toCharArray();
        int min =  Math.min(minChar(arra, arrb), minChar(arrb, arra));
        // int min = Integer.MAX_VALUE;
        for(char c = 'a'; c <= 'z'; c++){
            int sum = 0;
            for(char ca : arra){
                if(ca != c){
                    sum++;
                }
            }
            for(char cb : arrb){
                if(cb != c){
                    sum++;
                }
            }
            min = Math.min(min, sum);
        }
        return min;
    }
    private static int minChar(char[] a, char[] b){
        int min = Integer.MAX_VALUE;
        for(char c = 'a'; c < 'z'; ++c){
            int sum = 0;
            for(char ca : a){
                if(ca > c){
                    sum++;
                }
            }
            for(char cb : b){
                if(cb <= c){
                    sum++;
                }
            }
            min = Math.min(min, sum);
        }
        return min;
    }
}

第四题、2055. 蜡烛之间的盘子

  1. 题目链接:2055. 蜡烛之间的盘子
  2. 思路分析:
    用左右指针遍历,每个qs[i]中的两个数,l = qs[i][0]r = qs[i][1],当做右指针都遇到'|'时,就返回两指针之间‘*’的数量
  3. 代码:
class Solution {
    public int[] platesBetweenCandles(String s, int[][] qs) {
        char[] cs = s.toCharArray();
        int n = cs.length, m = qs.length;
        int[] l = new int[n], r = new int[n];
        int[] sum = new int[n + 1];
        for (int i = 0, j = n - 1, p = -1, q = -1; i < n; i++, j--) {
            if (cs[i] == '|') p = i;
            if (cs[j] == '|') q = j;
            l[i] = p; r[j] = q;
            sum[i + 1] = sum[i] + (cs[i] == '*' ? 1 : 0);
        }
        int[] ans = new int[m];
        for (int i = 0; i < m; i++) {
            int a = qs[i][0], b = qs[i][1];
            int c = r[a], d = l[b];
            if (c != -1 && c <= d) ans[i] = sum[d + 1] - sum[c];
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值