思路:
题目的主要信息:
- 数组a是初始时水桶里的水
- 数组p是每次询问后,要求水桶中水相同的水桶数量
- 一共是q次查询,每次需要找到使水桶中拥有相同水量的水桶数量达到p中要求的最少花费,即每次加水量最少
方法一:动态规划+前缀和
具体做法:
我们用(下标1开始)表示前i个数的和。
对于某一次查询,我们要求需要有个相同水量的水桶,那我们知道经过第次查询,前面的已经相同了,所以我们后续找要添加到的标杆水桶就从下标为开始,于是利用前面求到的前缀和,我们可以得到总花费,即标杆水桶的水量乘上需要相同的个数,减去前面已经有的水量(这个通过前缀和相减得到),遍历后续数组找到这个花费的最小值即可。找到之后,我们需要将标杆水桶之前的水量都修改为标杆水桶的水量,开始下一轮查询。
class Solution { public: vector<int> solve(int n, int q, vector<int>& a, vector<int>& p) { vector<int> res(q, 0); //q次查询的返回值 vector<int> dp(n + 1, 0); sort(a.begin(), a.end()); //由小到大排序 for(int i = 0; i < q; i++){ for(int j = 1; j <= n; j++) dp[j] = dp[j - 1] + a[j - 1]; //计算前缀和 int Min = INT_MAX, sum = 0; int pos = 0; //记录修改到水一样多时的位置 for(int j = p[i]; j <= n; j++){ //寻找最小花费时间,前面p[i]个已经相等,从后面开始找 sum = a[j - 1] * p[i] - (dp[j] - dp[j - p[i]]); if(sum < Min){ Min = min(sum, Min); pos = j; } } for(int j = pos - 1; j > pos - p[i]; j--) //修改pos之前的 a[j - 1] = a[pos - 1]; res[i] = Min; } return res; } };
复杂度分析:
- 时间复杂度:,外循环,内部三个循环都是,循环外是一个排序
- 空间复杂度:,只有dp是辅助空间,res属于必要空间,不算额外空间
方法二:前缀和迭代
具体做法:
方法一中的动态规划借助了辅助数组,其实我们也可以不用。每次我们使用到的前缀和只有两个,因为我们可以用迭代的方式,用变量记录在迭代中出现的前缀和,其余思路与动态规划相似。
同时,我们还可以使用一个变量记录当前最大的相同水桶数,如果当前已经满足要求,我们便可以跳过一次运算,以节省时间。
class Solution { public: vector<int> solve(int n, int q, vector<int>& a, vector<int>& p) { vector<int> res(q, 0); sort(a.begin(), a.end()); //排序 int maxsame = 1, same = 1; for (int i = 1; i < n; i++){//找出数组中大小相同并且相同个数最多的元素的个数 if (a[i] == a[i - 1]) same++; else { maxsame = max(maxsame, same); same = 1; } } int Min = 0; int pos = 0; //pos为标杆水桶的下标 for (int i = 0; i < q; i++) { if (p[i] > maxsame) { //先与当前最大相同水桶数比较 int sum = 0; //前p[i]个数和 for (int j = 0; j < p[i]; j++) sum += a[j]; Min = a[p[i] - 1] * p[i] - sum; pos = p[i] - 1; for (int j = p[i]; j < n; j++) {//遍历数组,看是否有比上面时间更短的 sum -= a[j - p[i]] - a[j]; if (Min > a[j] * p[i] - sum) { Min = a[j] * p[i] - sum; pos = j; } } res[i] = Min; for (int j = pos - p[i] + 1; j < pos; j++) //修改pos之前的 a[j] = a[pos]; maxsame = p[i]; } } return res; } };
复杂度分析:
- 时间复杂度:,外循环,内三个循环都是,外部计算初始最大相同数复杂度为,相较于排序的可忽略
- 空间复杂度:,常数个变量,res是必要空间