• leetcode双周赛 45


    A:水题,求数组中只出现一次的元素的和。

     1 class Solution {
     2 public:
     3     int sumOfUnique(vector<int>& nums) {
     4         unordered_map<int,int> m;
     5         for(auto x:nums){
     6             m[x]++;
     7         }
     8         int res=0;
     9         for(auto x:m){
    10             if(x.second==1){
    11                 res+=x.first;
    12             }
    13         }
    14         return res;
    15     }
    16 };

    B:找出子数组和的绝对值的最大值。

    解法一:应用求最大子数组的双指针模型。

    最终的答案要么是正数(非常大),要么是负数(非常小),应用两遍求最大子数组的双指针模型就可以求出答案。

     1 class Solution {
     2 public:
     3     int maxAbsoluteSum(vector<int>& nums) {
     4         int n=nums.size();
     5         int l=0,r=0;
     6         int sum=0,res=0;
     7         while(r<n){
     8             sum+=nums[r];
     9             r++;
    10             while(sum<0){
    11                 sum-=nums[l];
    12                 l++;
    13             }
    14             res=max(res,sum);
    15         }
    16         l=0,r=0;
    17         sum=0;
    18         while(r<n){
    19             sum+=nums[r];
    20             r++;
    21             while(sum>0){
    22                 sum-=nums[l];
    23                 l++;
    24             }
    25             res=max(res,-sum);
    26         }
    27         
    28         return res;
    29     }
    30 };

    解法二:利用前缀和

    如果将原数组前缀和之后的话,就只需要枚举左右端点,但是时间上还是过不去。

    然后发现如果此时我们求子数组最大值,那么对于每一个右端点i,我们需要知道的是1~i-1中的最小值。

    如果求子数组的最小值,那么对于每一个右端点i,我们需要知道的是1~i-1中的最大值。

    所以在前缀后之后,维护max_val,min_val就可以了。

     1 class Solution {
     2 public:
     3     int maxAbsoluteSum(vector<int>& nums) {
     4         int n=nums.size();
     5         vector<int> s(n+1);
     6         for(int i=1;i<=n;i++){
     7             s[i]=s[i-1]+nums[i-1];
     8         }
     9         int max_val=0,min_val=0;//初始化为0是因为要求的是abs,所以不能初始化为无穷
    10                                 //而初始化为0正好满足选择空数组的情况
    11         int res=0;//初始状态就是选择空数组
    12         for(int i=1;i<=n;i++){
    13             res=max(res,abs(s[i]-max_val));
    14             res=max(res,abs(s[i]-min_val));
    15             max_val=max(max_val,s[i]);
    16             min_val=min(min_val,s[i]);
    17         }
    18         return res;
    19     }
    20 };

    C:给定一个字符串,若左端点==右端点,那么可以将左边和右边大于一个的字符删除。求删除后的最短长度。

    证明:如果删的话,一定尽可能地全部删掉。

        假设两边都不删完,那么下一次还是得删,所以不如删完。

        假设其中一边不删完,不妨设是左边,那么删完之后的字符串必定左端点不等于右端点,不如删完。

    所以每次如果左端点等于右端点的话,直接删完就好了。

    考试的时候的代码:

     1 class Solution {
     2 public:
     3     int minimumLength(string s) {
     4         int begin=0,end=s.size()-1;
     5         while(s[begin]==s[end]&&begin<end){
     6             int l=begin,r=end;
     7             while(l<=end&&s[l]==s[begin]) l++;
     8             while(r>=begin&&s[r]==s[end]) r--;
     9             if(l>r) return 0;
    10             begin=l,end=r;
    11         }
    12         return end-begin+1;
    13     }
    14 };

    更简洁的代码:

     1 class Solution {
     2 public:
     3     int minimumLength(string s) {
     4         int i=0,j=s.size()-1;
     5         while(i<j){
     6             if(s[i]!=s[j]) break;
     7             char c=s[i];
     8             while(i<=j&&s[i]==c) i++;
     9             while(i<=j&&s[j]==c) j--;
    10         }
    11         return j-i+1;
    12     }
    13 };

    D:给定n个区间,每个区间有一个价值,选择k个不相交的价值最大的区间,返回最大价值。

     因为计算f [ i ] [ j ]的时候,需要找到右端点小于i左端点的最右边的那个区间。

    所以我们可以将区间按照右端点排序,然后利用二分来寻找该区间。

    这样的话时间复杂度为n*k*log n 

     1 const int N=1e6+10;
     2 struct Q{
     3     int s,e,v;
     4     bool operator<(const Q& t){
     5         return e<t.e;
     6     }
     7 }q[N];
     8 class Solution {
     9 public:
    10     int maxValue(vector<vector<int>>& events, int k) {
    11         int n=events.size();
    12         vector<vector<int>> f(n+1,vector<int>(k+1));
    13         for(int i=1;i<=n;i++){
    14             q[i]={events[i-1][0],events[i-1][1],events[i-1][2]};
    15         }
    16         sort(q+1,q+1+n);
    17         for(int i=1;i<=n;i++){
    18             for(int j=1;j<=k;j++){
    19                 f[i][j]=f[i-1][j];//不选第i个
    20                 int l=0,r=i-1;
    21                 while(l<r){
    22                     int mid=l+r+1>>1;
    23                     if(q[mid].e<q[i].s) l=mid;
    24                     else r=mid-1;
    25                 }
    26                 f[i][j]=max(f[i][j] , f[r][j-1]+q[i].v);
    27             }
    28         }
    29         return f[n][k];
    30     }
    31 };
  • 相关阅读:
    CC2540-BLE4.0 学历笔记1之串口体验
    cc2530的PWM实现
    用qt写的一个简单到不能在简单的上位机
    在Kubuntu14.04中安装小企鹅输入法
    初始化umi项目
    工具杂记(三) -- zookeeper
    工具杂记(二) -- Centos7
    工具杂记(一) -- vagrant
    (一)Docker导学
    JVM随笔(二)之搜索类
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14394296.html
Copyright © 2020-2023  润新知