1. 程式人生 > 其它 >【LeetCode-142】環形連結串列 II

【LeetCode-142】環形連結串列 II

增減序列

最終的目的是讓整個序列相等

操作只有一種使\([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
此時可以考慮兩中情況

  1. 與差分序列首項想相加減
    這種情況因為改變首項,所以最終序列會改變,故會得到\(abs(p-q)\)種序列

  2. 與第\(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;
}