【七月算法】day08 前缀和

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

题目描述:

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

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

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

思路:

先计算一次所有学生需要的粉笔数sum,用k对其取余,这样就可以在一轮遍历中获得结果;

class Solution {
public:
    int chalkReplacer(vector<int>& chalk, int k) {
        long long sum = 0;
        int n = chalk.size();
        for (int i = 0; i < n; ++i) {
            sum += chalk[i];  
        }
        k %= sum;
        sum = 0;
        for (int i = 0; i < n; ++i) {
            sum += chalk[i];
            if (sum > k) {
                return i;
            }  
        }
        return -1;

    }
};

2256. 最小平均差

题目描述:

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

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

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

注意:

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

思路:

首先特判数组长度为1时,差值为0;

计算一次数组总和sum,然后分步计算部分和partsum,每计算一次部分和partsum,就可以计算前半部分partsum和后半部分sum-partsum的平均值的绝对差;这里就需要一个记录下标mini,和绝对差ans的变量。

注意是可以计算整个数组的平均值的。这里需要特写;

class Solution {
public:
    int minimumAverageDifference(vector<int>& nums) {
        long long sum = 0;
        long long partsum = 0;
        int ans = 100000020, mini = -1;
        int n = nums.size();
        if (n == 1) {
            return 0;
        }
        for (int i = 0; i < n; ++i) {
            sum += nums[i];
        }
        int val = 0;
        for (int i = 0; i < n; ++i) {
            partsum += nums[i];
            if (i != n -1) {
                val = abs(partsum/(i+1) - (sum - partsum)/(n-i-1));
            } else {
                val = sum / n;
            }

            if (val < ans) {
                ans = val;
                mini = i;
            }

        }
        return mini;
    }
};

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

题目描述:

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

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

a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母 。
b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母 。
a 和 b 都 由 同一个 字母组成。
返回达成目标所需的 最少 操作数。

思路:

对于前两种情况是一样的,只需要实现一个函数,然后交换参数就能复用;
对于第三种情况,直接枚举26个英文字母,取最小修改值就是答案了;
而对于前两种情况,只需要枚举一个字母分界点x,然后字符串a全部变成小于x的字符,字符串b全部变成大于x的字符,统计操作次数取最小值即可。

class Solution {
    int getminchch (const string &a, const string &b) {
        int ans = 1000000000;
        for (char x = 'a'; x < 'z'; ++x) {
            int sum = 0;
            for (int i = 0; i < a.size(); ++i) {
                sum += (a[i] <= x ? 0 : 1);
            }
            for (int i = 0; i < b.size(); ++i) {
                sum += (b[i] > x ? 0 : 1);
            }
            ans = min(ans, sum);
        }
        return ans;
    }
public:
    int minCharacters(string a, string b) {
        int ret = min(getminchch(a, b), getminchch(b, a));
        for (char x = 'a'; x <= 'z'; ++x) {
            int sum = 0;
            for (int i = 0; i < a.size(); ++i) {
                sum += (a[i] == x ? 0 : 1);
            }
            for (int i = 0; i < b.size(); ++i) {
                sum += (b[i] == x ? 0 : 1);
            }
            ret = min(ret, sum);
        }
        return ret;
    }
};
//重做

2055. 蜡烛之间的盘子

题目描述:

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

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

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

思路:

为了方便做前缀和的差分,我们首先可以将字符串的第一个字符填充一下;
用suml表示蜡烛的前缀和,用sump表示盘子的前缀和;
对于每个给定的区间,利用二分查找找到最左边的蜡烛和最右边的蜡烛,然后利用差分计算两者之间的蜡烛数量即可;

class Solution {
    int getMinL(int suml[100010], int l, int r) {
        int pre = l - 1;
        int ans = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (suml[mid] - suml[pre]) {
                r = mid -1;
                ans = mid;
            } else {
                l = mid + 1;
            }
        }
        return ans;
    }
    int getMaxL(int suml[100010], int l, int r) {
        int prer = r;
        int ans = -1;
        --l;
        --r;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (suml[prer] - suml[mid]) {
                l = mid + 1;
                ans = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return ans;
    }


public:
    vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
        int suml[100010], sump[100010];
        vector<int> ans;
        suml[0] = sump[0] = 0;
        s = "#"+ s;

        for (int i = 1; i < s.length(); ++i) {
            suml[i] = suml[i-1] + (s[i] == '|' ? 1 : 0);
            sump[i] = sump[i-1] + (s[i] == '*' ? 1 : 0);
        }
        for (int i = 0; i < queries.size(); ++i) {
            int l = queries[i][0] + 1;
            int r = queries[i][1] + 1;
            int ll = getMinL(suml, l, r);
            if (ll == -1) {
                ans.push_back(0);
            } else {
                int rr = getMaxL(suml, l, r);
                ans.push_back(sump[rr]- sump[ll]);
            }
        }
        return ans;
    }
};
//重做

猜你喜欢

转载自blog.csdn.net/ilovejujube/article/details/125676095