当前位置: 代码迷 >> 综合 >> Leetcode 一样的水
  详细解决方案

Leetcode 一样的水

热度:6   发布时间:2024-02-13 03:32:16.0

题目描述

有n个水桶,第i个水桶里面水的体积为Ai,你可以用1秒时间向一个桶里添加1体积的水。

有q次询问,每次询问一个整数pi,你需要求出使其中pi个桶中水的体积相同所花费的最少时间。

对于一次询问如果有多种方案,则采用使最终pi个桶中水的体积最小的方案。

 

示例1

输入

复制

4,3,[1,2,3,4],[2,2,4]

输出

复制

[1,0,5]

说明

第一次:花费一秒变为 2 2 3 4第二次:已经存在两个水的体积一样的桶第三次:花费五秒从2 2 3 4变为4 4 4 4

 

思路:考察一次查询,让k个水桶水量一样

  • 先将水桶水量升序排序
  • 滑动窗口的方式,依次考察不同区间段,使得水量相等的时间
  • 记录下最小的时间,以及区间端点

关键点:

常规思路,需要采取多重遍历,时间复杂度很高

注意到:前一次窗口花费时间为T  那么下一个窗口内所需时间为

  • T+=(L-1)*(A[i]-A[i-1])          即增加上由于窗口新加入的A[i]元素,使得整体均值提高,这部分需要增加时间 A[i]-A[i-1]
  • T-=A[i-1]-A[0]                     即减去由于窗口右移动,省去的时间开销   A[i-1]-A[0]

即一次遍历,即可获取使得k个达到相同值得最小时间

vector<int> solve(int n, int q, vector<int>& a, vector<int>& p) {// write code herevector<int> res;sort(a.begin(),a.end());//排序//滑动窗口for(int i=0;i<q;i++){int len=p[i];//滑动窗口的长度int index_j=0;//标记下标int time=a[len-1]*len;//最少时间for(int j=0;j<len;j++)time-=a[j];//获得差值int min=time;//最少时间for(int s=len;s<n;s++) //s为起始点{//每次滑动一次 需要累加上由于均值变大导致的增加量  同时减去开头元素的开销time+=(a[s]-a[s-1])*(len-1)-(a[s-1]-a[s-len]);if(time<min){min=time;index_j=s-len+1;}               } //结束之后  按照最少时间方案调整桶 for(int s=index_j;s<index_j+len;s++)a[s]=a[index_j+len-1];          res.push_back(min);}     return res;  }