leetcode周赛 238

A:水题

 1 class Solution {
 2 public:
 3     int sumBase(int n, int k) {
 4         int res=0;
 5         while(n){
 6             res+=n%k;
 7             n/=k;
 8         }
 9         return res;
10     }
11 };

 

 

B:给定一个数组和一个可操作次数,每次操作可将某一个元素加一,问操作之后的最大的频数数目是多少。

数组排序之后。

性质一:答案的最终频数一定可以是原数组中的数

 

性质二:对于一个确定的目标,在往左寻找最大频数的过程中操作次数单调增加

二分解法

对于一个 i(目标) 和 j(左端)操作次数等于 (a [ i ] - a [ j ] ) + (a [ i ] - a [ j+1 ] ) + ....+(a [ i ] - a [ i ] ) = (j-i+1) a[i] - ( a[j]+a[j+1]+...+a[i] )

后者可用前缀和进行计算

 1 typedef long long LL;
 2 class Solution {
 3 public:
 4     vector<LL> s;
 5     LL get_op(int i,int j,vector<int>&nums){
 6         return nums[j]*(j-i+1ll)-(s[j+1]-s[i]);
 7     }
 8     int maxFrequency(vector<int>& nums, int k) {
 9         sort(nums.begin(),nums.end());
10         s.resize(nums.size()+1);
11         for(int i=1;i<=nums.size();i++) s[i]=s[i-1]+nums[i-1];
12         int res=0;
13         for(int i=0;i<nums.size();i++){
14             int l=0,r=i;
15             while(l<r){
16                 int mid=l+r>>1;
17                 if(get_op(mid,i,nums)<=k){
18                     r=mid;
19                 }else{
20                     l=mid+1;
21                 }
22             }
23             res=max(res,i-l+1);
24         }
25         return res;
26     }
27 };

设定i为区间左端点,j为区间右端点,将区间内全部的数变成nums [ j ] ,操作次数小于k

性质三:当 j 往右移动,左端点 i 同时跟着往右移动

 

 

 双指针算法

计算操作次数同样用前缀和

 1 typedef long long LL;
 2 class Solution {
 3 public:
 4     vector<LL> s;
 5     LL get_op(int i,int j,vector<int>&nums){
 6         return nums[j]*(j-i+1ll)-(s[j+1]-s[i]);
 7     }
 8     int maxFrequency(vector<int>& nums, int k) {
 9         sort(nums.begin(),nums.end());
10         s.resize(nums.size()+1);
11         for(int i=1;i<=nums.size();i++) s[i]=s[i-1]+nums[i-1];
12         int res=0;
13         int i=0;
14         for(int j=0;j<nums.size();j++){
15             while(get_op(i,j,nums)>k){
16                 i++;
17             }
18             res=max(res,j-i+1);
19         }
20         return res;
21     }
22 };

 

 

C:可以直接模拟求解,注意分类讨论即可。

 1 class Solution {
 2 public:
 3     int longestBeautifulSubstring(string s) {
 4         string p="aeiou";
 5         int res=0;
 6         for(int i=0;i<s.size();i++){
 7             if(s[i]!='a') continue;
 8             int j=i,k=0;
 9             while(j<s.size()){
10                 if(s[j]==p[k]) j++;
11                 else{
12                     if(k==4) break;
13                     if(s[j]==p[k+1]) j++,k++;
14                     else break;
15                 }
16                 if(k==4)
17                     res=max(res,j-i);//不需要加一,j-1才是确定的
18             }
19             i=j-1;
20         }
21         return res;
22     }
23 };

 

 

D:线性规划问题。

单独分析 i 这个点。

 

对于 i 这个点前边和后边对他高度的限制如图所示。

我们可以通过记录截距来记录每一条直线,也就很容易算出一个点的最高高度是多少了。

但是这样的话我们还是得算1e9次,但是观察到总共只有1e5个限制。

 

假设 i 和 j 之间是没有别的限制的话,i,j 之间的最大高度就是 i 和 j 以及他们限制交点的最低点(如果焦点在i,j之间的话)

 1 class Solution {
 2 public:
 3     int maxBuilding(int n, vector<vector<int>>& h) {
 4         typedef long long LL;
 5         h.push_back({1,0});
 6         sort(h.begin(),h.end());
 7         if(h.back()[0]!=n){
 8             h.push_back({n,n-1});
 9         }
10         LL m=h.size();
11         vector<LL> f(m+1,INT_MAX),g(m+1,INT_MAX);
12         f[0]=-1;
13         for(int i=1;i<m;i++){
14             int x=h[i][0],y=h[i][1];
15             f[i]=min(f[i-1],(LL)y-x);
16         }
17         for(int i=m-1;i>=0;i--){
18             int x=h[i][0],y=h[i][1];
19             g[i]=min(g[i+1],(LL)y+x);
20         }
21         LL res=0;
22         for(int i=0;i<m;i++){
23             int x=h[i][0];
24             if(i){//防止数组越界,计算h[i-1][0]和h[i][0]之间的最高建筑高度
25                 LL Y=(f[i-1]+g[i])/2;
26                 LL X=Y-f[i-1];
27                 if(x>=h[i-1][0]&&X<=h[i][0])
28                     res=max(res,Y);
29             }
30             res=max(res,min(x+f[i],g[i]-x));
31         }
32         //下面这样写也是可以的
33 //         for(int i=0;i<m;i++){
34 //             int x=h[i][0];
35 //             if(i<m-1){
36 //                 LL Y=(f[i]+g[i+1])/2;
37 //                 LL X=Y-f[i];
38 //                 if(x>=h[i][0]&&X<=h[i+1][0])
39 //                     res=max(res,Y);
40 //             }
41 //             res=max(res,min(x+f[i],g[i]-x));
42 //         }
43         
44         return res;
45     }
46 };

 

posted on 2021-04-25 16:18  greenofyu  阅读(45)  评论(0编辑  收藏  举报