Leetcode 貪心:差值調整
題目描述
有n個箱子,第i個箱子一開始有ai個球,你可以進行最多k次操作,每次操作可以從一個箱子拿走一個球或者放入一個球。第i個箱子最多能裝wi個球,裝滿了之後不能再往這個箱子裡面放球。如果一個箱子為空,就不能從裡面拿球。
設相鄰箱子的球的數量的差的平方中的最大值為x,求進行最多k次操作之後x最小可以是多少。
輸入
5,4,[12,4,7,9,1],[15,15,15,15,15]
輸出
36
往第2個箱子放2個球,往第5個箱子放2個球得到[12,6,7,9,3],此時相鄰箱子的球數差值為[-6,1,2,-6],平方後為[36,1,4,36],其中最大值為36
【思路】
本題的問題是使得經過一定的次數,使得相鄰的差值平方儘可能小(即:所有數儘可能靠近)
貪心策略:
每一輪找到相鄰差值最大的那兩個數a[index]=>a[index+1],有兩種策略:較大的那個數減少,或者較小的那個數增大。
具體的策略是:
如果當前a[index]<a[index+1]即 是增大的:分三大類情況:
- 當前index==0 第一二個數:那麼分析其後一組是否為增大或減少,選擇相應的策略
- 當前index==n-2 最後兩個數index-2 index-1 那麼分析前面一組是否為增大或減少,選擇相應的策略
- 其它情況,需要同時分析前面一組,後面一組的情況,特別點(如三組都增大:需要比較斜率大小)
如果當前a[index]<a[index+1]即 是減少的 ,同上所述
優化策略:
由於有w[i]上限限制,當發現較小的那個數a[index]==w[index] 達到上限,那麼直接較大的那個數減少即可。
實現程式碼:
int solve(int n, int k, vector<int>& a, vector<int>& w) {
for(int i=0;i<k;i++) //總共需要調整k次
{
//首先計算出當前相鄰差值最大的index
vector<int> dst(n-1,0);
int index=-1;
int _max_dst=0;
for(int i=0;i<n-1;i++)
{
dst[i]=a[i+1]-a[i];//dst[i]
if(dst[i]*dst[i]>_max_dst)
{
_max_dst=dst[i]*dst[i];
index=i;
}
}
//那麼 相鄰值相差最大的為 a[index]和a[index+1]
if(index==-1)
continue;
if(dst[index]>0) //若該組為增大 那麼兩種策略:前面的數增大 或者 後面的數減少
{
if(index==n-2) //如果這是最後兩個數 0=>n-1 dst[n-2]=a[n-1]-a[n-2]
{
if(index-1>=0 && dst[index-1]<0) //如果前面一組是減少的
{
if(a[index]<w[index]) //優先選擇當前Index++
{
a[index]++;
} else{ //否則後面那個數 減少
a[index+1]--;
}
} else
{
a[index+1]--;//那麼直接最後那個數減少
}
}
else if(index==0) //第一、二個數
{
if( (index+1<=n-2 && dst[index+1]<0) || a[index]==w[index]) //後面一組是減少的 或者較小的那個數不能增大了 那麼直接index+1減少
{
a[index+1]--;
} else
{
a[index]++; //後面一組也是增大 那麼當前第一個數 增大
}
} else
{
if(dst[index+1]<0) //後面一組是減少的 那麼直接index+1減少
a[index+1]--;
else
{
if(dst[index-1]<0) //前面一組是減少的
{
if(a[index]<w[index]) //優先選擇index++
a[index]++;
else //前面一個數不能增大 那麼只能後面的數減少
a[index+1]--;
} else //三組都是增大的
{
if(dst[index-1]<dst[index+1] || a[index]==w[index]) //前面那組 增大趨勢更大
a[index+1]--;
else
{
a[index]++;
}
}
}
}
} else //當前a[index] => a[index+1]是減少的
{
if(index==n-2) //如果這是最後兩個數
{
if((index-1>=0 && dst[index-1]>0) || a[index+1]==w[index+1]) //如果前面一組是增大的 或者較小的那個數不能增大
{
a[index]--;
} else
{
a[index+1]++;//那麼直接最後那個數減少
}
}
else if(index==0) //第一、二個數
{
if((index+1<=n-2 && dst[index+1]<0 ) || a[index+1]==w[index+1]) //後面一組是減少的 或者較小的那個數不能增大了
{
a[index]--;//那麼只能較大的那個數減少
} else
{
a[index+1]++;
}
} else
{
if(index+1<=n-2 && dst[index+1]>0) //後面一組是增大的
{
if(a[index+1]<w[index+1])
a[index+1]++; //較小的那個數增大
else
a[index]--;
}
else
{
if(index-1>=0 && dst[index-1]>0) //前面一組是增大的
{
a[index]--;//直接較大的數減少
} else //三組都是減少的 那麼需要權衡 前後兩組dst
{
if(dst[index-1]>dst[index+1] || a[index+1]==w[index+1]) //同時如果較小的那個數不能增大 那麼也直接減少較大的數
a[index]--;
else
{
a[index+1]++;
}
}
}
}
}
}
int res=0;
for(int i=0;i<n-1;i++)
{
res=max(res,(a[i+1]-a[i])*(a[i+1]-a[i]));
}
return res;
}
驗證程式碼:
int main()
{
vector<int> a={12,4,7,9,1};
vector<int> b={15,15,15,15,15};
cout<<solve(5,4,a,b)<<endl;
}
相關文章
- leetcode1546題解【字首和+貪心】LeetCode
- LeetCode:動態規劃+貪心題目整理LeetCode動態規劃
- 【LeetCode】貪心演算法–分發糖果(135)LeetCode演算法
- leetcode1552題解【二分+貪心】LeetCode
- 貪心
- LeetCode 55. 跳躍遊戲 ( 回溯 dp 貪心LeetCode遊戲
- LeetCode解題記錄(貪心演算法)(二)LeetCode演算法
- LeetCode解題記錄(貪心演算法)(一)LeetCode演算法
- leetcode - 1686 - 石子游戲 VI - 貪心 - 數學分析LeetCode
- leetcode:跳躍遊戲II(java貪心演算法)LeetCode遊戲Java演算法
- 力扣 leetcode 435. 無重疊區間 貪心力扣LeetCode
- 反悔貪心
- Supermarket(貪心)
- 【Leetcode每日一題】316. 去除重複字母(棧,貪心)LeetCode每日一題
- 關於學習心態的調整
- 貪心例題
- 貪心+搜尋
- HDU 5821 Ball(貪心)
- 貪心模式記錄模式
- 反悔貪心雜題
- 貪心演算法演算法
- 貪心、構造合集
- 貪心-刪數問題
- 貪心-*活動選擇
- 24/03/20 貪心(一)
- HDU 6047 Maximum Sequence (貪心)
- HDU 5813 Elegant Construction (貪心)Struct
- 漲薪【貪心】【快速冪】
- Least Cost Bracket Sequence(貪心)ASTRacket
- 刪數問題(貪心)
- 「貪心」做題記錄
- [反悔貪心] Add One 2
- 貪心 做題筆記筆記
- 7.5 - 貪心篇完結
- 貪心演算法Dijkstra演算法
- 牛客 tokitsukaze and Soldier 貪心
- Leetcode 最小調整數+滑動視窗遞增子序列LeetCode
- 學一下貪心演算法-學一下貪心演算法演算法