zoukankan      html  css  js  c++  java
  • 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 };
  • 相关阅读:
    洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告
    洛谷 P1338 末日的传说 解题报告
    洛谷 P3952 时间复杂度 解题报告
    vector-erase
    STL之--插入迭代器(back_inserter,inserter,front_inserter的区别
    STL之--插入迭代器(back_inserter,inserter,front_inserter的区别
    vector-end
    vector-end
    vector-empty
    vector-empty
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14700797.html
Copyright © 2011-2022 走看看