A:水题,给定01串,问连续的0更长还是连续的1更长。
直接遍历即可。
1 class Solution { 2 public: 3 bool checkZeroOnes(string s) { 4 int res1=0,res0=0; 5 int cnt1=0,cnt0=0; 6 for(int i=0;i<s.size();i++){ 7 if(s[i]=='1'){ 8 res0=max(res0,cnt0); 9 cnt0=0; 10 cnt1++; 11 }else if(s[i]=='0'){ 12 res1=max(res1,cnt1); 13 cnt1=0; 14 cnt0++; 15 } 16 } 17 res0=max(res0,cnt0); 18 res1=max(res1,cnt1); 19 return res1>res0; 20 } 21 };
B:https://leetcode-cn.com/contest/weekly-contest-242/problems/minimum-speed-to-arrive-on-time/
可以发现走完全程所需的时间随着速度的增加而减少(单调不增)
故可以直接二分速度。计算当前速度所需的时间,同给定的时间进行比较。
【注】速度是整数。
考试时候的double+ceil写法:
1 class Solution { 2 public: 3 const double eps=1e-8; 4 double cal(vector<int>& dist,double speed){ 5 double res=0; 6 int n=dist.size(); 7 for(int i=0;i<n-1;i++){ 8 res+=ceil(dist[i]/speed); 9 } 10 res+=dist[n-1]/speed; 11 return res; 12 } 13 int minSpeedOnTime(vector<int>& dist, double hour) { 14 int n=dist.size(); 15 double l=0,r=2e7; 16 while(r-l>=eps){ 17 double mid=(l+r)/2; 18 if(cal(dist,mid)<=hour) r=mid; 19 else l=mid; 20 } 21 if(fabs(l-2e7)<eps) 22 return -1; 23 return ceil(l); 24 } 25 };
可以写整数二分,而不用double(不用考虑精度问题)
1 class Solution { 2 public: 3 double cal(vector<int>& dist,int speed){ 4 double res=0; 5 int n=dist.size(); 6 for(int i=0;i<n-1;i++){ 7 res+=(dist[i]+speed-1)/speed; 8 } 9 res+=(double)dist.back()/speed; 10 return res; 11 } 12 int minSpeedOnTime(vector<int>& dist, double hour) { 13 int n=dist.size(); 14 int l=1,r=2e7;//l一定初始化为1,因为如果初始化为0的话,会出现除0的情况 15 while(l<r){ 16 int mid=(l+r)/2; 17 if(cal(dist,mid)<=hour) r=mid; 18 else l=mid+1; 19 } 20 if(r==2e7) 21 return -1; 22 return r; 23 } 24 };
C:跳跃游戏,一个点 i 能够跳到 j 的充要条件是 s [ j ] ='1' ,且 j >= i+minJump && j<=i+maxJump .
这样的话,对于一个点也只能够从 j -maxJump ~ j - minJump 跳过来,故可以直接通过DP求解。
考试时候写法:
1 const int N=1e5+10; 2 bool f[N]; 3 class Solution { 4 public: 5 bool canReach(string s, int minJump, int maxJump) { 6 memset(f,0,sizeof f); 7 int n=s.size(); 8 s=' '+s; 9 f[1]=true; 10 deque<int> q; 11 q.push_back(1); 12 for(int j=1;j<=s.size();j++){//对于j,它可以从j-maxjunp~j-minjump调过来 13 while(q.size()&&q.front()<j-maxJump) q.pop_front(); 14 while(q.size()&&q.back()>j-minJump) q.pop_back();//这两个循环保证队列中的数是可以跳到j的 15 if(j-minJump>=1&&f[j-minJump]) q.push_back(j-minJump); 16 if(s[j]=='1') f[j]=false; 17 else if(s[j]=='0'){ 18 if(q.size()) 19 f[j]=true; 20 } 21 } 22 return f[n]; 23 } 24 };
考试错在没加第14行,比如“000000” minjump =4 maxjump=5 第二个字符就是不能被跳到的,但是少14行就不能把1弹出去。
也可以用前缀和来记录1~i 区间内有多少个可以到的点,这样的话就可以在O(1)的时间内求出 j - maxJump ~ j - minJump是否有可以到达的点了。
1 const int N=1e5+10; 2 bool f[N]; 3 int sum[N]; 4 class Solution { 5 public: 6 bool canReach(string str, int a, int b) { 7 8 memset(f,0,sizeof f); 9 memset(sum,0,sizeof sum); 10 int n=str.size(); 11 str=' '+str; 12 f[1]=1; 13 sum[1]=1; 14 for(int i=2;i<=n;i++){ 15 sum[i]=sum[i-1]; 16 if(str[i]=='0'&&i-a>=1){ 17 int r=i-a,l=max(1,i-b); 18 if(sum[r]-sum[l-1]>0){ 19 f[i]=1; 20 sum[i]++; 21 } 22 } 23 } 24 // for(int i=1;i<=n;i++) cout<<sum[i]<<" "; 25 return f[n]; 26 } 27 };
D:因为是Alice先手,所以题目描述的Alice目标是使得P_Alice - P_Bob最大,而Bob目标是使得他最小,意思是Alice得分一定比Bob高。
1 class Solution { 2 public: 3 int stoneGameVIII(vector<int>& stones) { 4 int n=stones.size(); 5 vector<int> f(n); 6 vector<int> pre(n+1); 7 for(int i=1;i<=n;i++) pre[i]=pre[i-1]+stones[i-1]; 8 f[n-1]=pre[n]; 9 for(int i=n-2;i>=1;i--){ 10 f[i]=max(f[i+1],pre[i+1]-f[i+1]); 11 } 12 return f[1]; 13 } 14 };