【LeetCode-142】環形連結串列 II
阿新 • • 發佈:2021-08-07
增減序列
最終的目的是讓整個序列相等
操作只有一種使\([l,r]\)區間全都\(+1\)
既然整個序列相等,那麼整個序列的差分序列應為0
操作的話就可以轉化為\(a[l]+=1,a[r+1]-=1\)
求的是最少操作次數
通過原數列,我們先求一個原始的差分序列,然後每次操作使,正數-1,負數+1,這樣就使差分序列往目標:靠近 0序列
(當然差分序列第1項不用為0,而且首項可以為任何數,思考為什麼?)
設正數的和p,負數絕對值和q,那麼就很容易的到一個最少操作次數 \(max(p,q)\)
(簡單描述下怎麼來的,操作\(min(p,q)\)次後,p,q中小的變為0,還剩\(abs(p-q)\)次 ,所以最少操作次數 \(min(p,q)+abs(p-q)=max(p,q)\)
至於最少操作後的結果
操作\(min(p,q)\)次後,那麼一定剩下幾項不為0
此時可以考慮兩中情況
-
與差分序列首項想相加減
這種情況因為改變首項,所以最終序列會改變,故會得到\(abs(p-q)\)種序列 -
與第\(n+1\)項相加減
這種情況並不改變首項,只有一種序列(第n+1項無論怎麼變,都不影響最終序列,也可以思考為什麼)
總的來說會得到\(abs(p-q)+1\)種方案
- code
#include<iostream> using namespace std; const int maxn=1e5+10; int a[maxn];int n; int cf[maxn]; long long p=0,q=0; long abs(long x){ return x<0?-x:x; } int main(){ cin>>n; for(int i=1;i<=n;++i){ cin>>a[i]; cf[i]=a[i]-a[i-1]; } for(int i=2;i<=n;++i){ if(cf[i]>0) p+=cf[i]; if(cf[i]<0) q-=cf[i]; } cout<<max(p,q)<<endl<<abs(p-q)+1<<endl;return 0; }