標籤:blog http io ar os for on 2014 art
在一個環形路徑上分布著n個加油站,從一個加油站到下一個加油站會耗油。要找出一個起始點,從這個起始點出發,存油量>=耗油量。解保證唯一。
這要求在路徑上不能出現非負的。
如果找出存油量最大的子序列,則可確保儘可能走完全程(貪心思想)。
因此,需要在環形數組中找一個最大子序列和。最大子序列和是很經典的DP問題,而針對環形約束,採用的是將數組複製一份並放到原數組最後,然後採用普通的最大子序列求解。其間,需要記錄起始位置(這是最終要求的),走過的網站數(網站數不能超過n,這是環形數組,長度為2n),最大的子序列和。在長度大於n的時候,需要向後調整起始位置,需要滿足起始位置不為負數。
複雜度O(2n)=>O(n)
class Solution {public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { vector<int>vt(gas.size()*2); int i,mx=-1,sum=0,n=gas.size(); for(i=0;i<n;++i){ vt[i]=vt[i+n]=gas[i]-cost[i]; sum+=vt[i]; } if(sum<0)return -1; int m=n*2,j=0,st=0,mst=-1,step=0; sum=0; for(i=0;i<m&&st<n;++i){ sum+=vt[i]; ++step; if(sum<0){ step=0;sum=0;st=i+1; continue; } if(step>n){ j=st;sum-=vt[j++],step--; while(j<i&&vt[j]<0)sum-=vt[j++],step--; st=j; } if(sum>mx){ mx=sum,mst=st; } } return mst; }};
環形數組的最大子序列和問題這裡介紹了採用求非環形數組的最大子序列maxv和和最小子序列和minv,然後環形數組最大子序列和答案為max(maxv,total-minv),如果是total-minv值更大,則其實位置為最小子序列和的終止位置的下一個位置。
int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { int i,mx=0,sum=0,n=gas.size(),d,sum2=0,mn=0,end=0,tot=0,start=0,mst=0; for(i=0;i<n;++i){ d=gas[i]-cost[i]; sum+=d; tot+=d; if(sum<0){ sum=0;start=i+1; } if(sum>mx){ mx=sum;mst=start; } sum2+=d; if(sum2>0){ sum2=0; } if(sum2<mn){ mn=sum2; end=i; } } return tot<0?-1:(tot-mn>mx?(end+1)%n:mst); }
[LeetCode]Gas Station 最大子序列和,貪心