zoukankan      html  css  js  c++  java
  • leetcode周赛 239

    A:水题,直接枚举即可。

     1 class Solution {
     2 public:
     3     int getMinDistance(vector<int>& nums, int target, int start) {
     4         int res=0,seq=INT_MAX;
     5         for(int i=0;i<nums.size();i++){
     6             if(nums[i]==target&&abs(i-start)<seq){
     7                 seq=abs(i-start);
     8                 res=i;
     9             }
    10         }
    11         return abs(start-res);
    12     } 
    13 };

    B:直接枚举每一段有多少个字母就好了时间(2e19),不过得注意有19位,所以得用ULL来存。

    考试写的dfs版本:

     1 typedef unsigned long long LL;
     2 class Solution {
     3 public:
     4     bool res=false;
     5     LL get(LL l,LL r,string s){
     6         LL res=0;
     7         for(LL i=l;i<=r;i++){
     8             res=res*10+s[i]-'0';
     9         }
    10         return res;
    11     }
    12     void dfs(LL now,LL pre,string& s,LL cnt){
    13         if(now>=s.size()&&cnt>=2){
    14             res=true;
    15             return ;
    16         }
    17         for(LL i=now;i<s.size();i++){
    18             LL num=get(now,i,s);
    19             if((now==0&&num<pre)||num==pre-1){
    20                 dfs(i+1,num,s,cnt+1);
    21             }
    22         }
    23 
    24     }
    25     bool splitString(string s) {
    26         dfs(0,0x3f3f3f3f3f3f3f3f,s,0);
    27         return res;
    28     }
    29 };

    二进制枚举版本:

     1 typedef unsigned long long LL;
     2 class Solution {
     3 public:
     4     bool splitString(string s) {
     5         int n=s.size();
     6         for(int i=1;i < 1<<(n-1);i++){//i是四位,从1开始是至少有一个分割线
     7             unsigned long long x=s[0]-'0';
     8             unsigned long long pre=-1;//补码,全一
     9             bool flag=true;
    10             for(int j=0;j<n-1;j++){
    11                 if(i>>j&1){
    12                     if(pre!=-1&&x!=pre-1){
    13                         flag=false;
    14                         break;
    15                     }
    16                     pre=x;
    17                     x=s[j+1]-'0';
    18                 }else{
    19                     x=x*10+s[j+1]-'0';
    20                 }
    21             }
    22             if(x!=pre-1) flag=false;
    23             if(flag) return true;
    24         }
    25         return false;
    26     }
    27 };

    C:考试的时候想的并不是很明白,复习的时候发现考察逆序对的问题,考试的时候阴差阳错的用冒泡的思想解决了。

    考试的时候的代码:

     1 class Solution {
     2 public:
     3     int getMinSwaps(string num, int k) {
     4         string tnum=num;
     5         for(int i=0;i<k;i++)
     6             next_permutation(tnum.begin(),tnum.end());
     7         int res=0;
     8         for(int i=0;i<num.size();i++){
     9             if(num[i]!=tnum[i]){
    10                 int tar=i+1;
    11                 while(num[i]!=tnum[tar]) tar++;
    12                 for(int j=tar;j>i;j--){
    13                     swap(tnum[tar],tnum[tar-1]);
    14                     tar--;
    15                     res++;
    16                 }
    17             }
    18         }
    19         return res;
    20     }
    21 };

    补题时候的代码:

    还存在一个问题就是如果存在两个相同的元素的话如何对应。

     

    因为只能交换相邻元素,显而易见是第一种,第二种会多出2*s的交换次数。

     1 class Solution {
     2 public:
     3     int getMinSwaps(string a, int k) {
     4         string b=a;
     5         for(int i=0;i<k;i++)
     6             next_permutation(b.begin(),b.end());
     7         int n=b.size();
     8         vector<int> c(n);//存储a中的元素在b中的位置
     9         vector<bool> vis(n);
    10         for(int i=0;i<n;i++){
    11             char ca=a[i];
    12             for(int j=0;j<n;j++){
    13                 if(!vis[j]&&ca==b[j]){
    14                     c[i]=j;
    15                     vis[j]=true;
    16                     break;
    17                 }
    18             }
    19         }
    20         //目的:把c变成正序
    21         //因为n=1e3,冒泡排序即可,若n过大的话,得用归并
    22         int res=0;
    23         for(int i=0;i<n;i++){
    24             for(int j=0;j<n-i-1;j++){
    25                 if(c[j]>c[j+1]){
    26                     swap(c[j],c[j+1]);
    27                     res++;
    28                 }
    29             }
    30         }
    31         return res;
    32     }
    33 };

    D:可以用并查集做,这是个经典模型(参考AcWing疯狂的馒头)

    并查集初始化之后,我们将优先级高的先操作,本题优先级高的就是区间长度短的。

    每次区间操作之后将一个区间删除(方法是让每一个都指向他的后一个元素),同时记录每一个元素对应的答案。

    class Solution {
    public:
        vector<int> p,w;
        vector<int> minInterval(vector<vector<int>>& segs, vector<int>& queries) {
            sort(segs.begin(),segs.end(),[](vector<int>&a,vector<int>&b){
                return a[1]-a[0]+1 < b[1]-b[0]+1;
            });
            const int n=1e7+10;
            p.resize(n+1);
            w.resize(n+1,-1);
            for(int i=0;i<=n;i++) p[i]=i;
            for(auto& s:segs){
                int l=s[0],r=s[1];
                int len=s[1]-s[0]+1;
                while(find(l)<=r){
                    l=find(l);
                    w[l]=len;
                    p[l]=l+1;
                }
            }
            vector<int> res;
            for(auto& q:queries){
                res.push_back(w[q]);
            }
            return res;
        }
        int find(int x){
            if(p[x]!=x)
                p[x]=find(p[x]);
            return p[x];
        }
    };

    但是因为本题n为1e7,时间复杂度为nlogn,会超时

    观察到区间数目和查询数目只有1e5,可以用离散化优化

     1 class Solution {
     2 public:
     3     vector<int> xs;
     4     vector<int> p,w;
     5     vector<int> minInterval(vector<vector<int>>& segs, vector<int>& queries) {
     6         for(auto& s:segs) xs.push_back(s[0]),xs.push_back(s[1]);
     7         for(auto& q:queries) xs.push_back(q);
     8         sort(xs.begin(),xs.end());
     9         xs.erase(unique(xs.begin(),xs.end()),xs.end());
    10         //以上为离散化
    11         sort(segs.begin(),segs.end(),[](vector<int>&a,vector<int>&b){
    12             return a[1]-a[0]+1 < b[1]-b[0]+1;
    13         });
    14         int n=xs.size();
    15         p.resize(n+1);
    16         w.resize(n+1,-1);
    17         for(int i=0;i<=n;i++) p[i]=i;
    18         for(auto& s:segs){
    19             int l=get(s[0]),r=get(s[1]);
    20             int len=s[1]-s[0]+1;
    21             while(find(l)<=r){
    22                 l=find(l);
    23                 w[l]=len;
    24                 p[l]=l+1;
    25             }
    26         }
    27         vector<int> res;
    28         for(auto& q:queries){
    29             res.push_back(w[get(q)]);
    30         }
    31         return res;
    32     }
    33     int find(int x){
    34         if(p[x]!=x)
    35             p[x]=find(p[x]);
    36         return p[x];
    37     }
    38     int get(int x){
    39         return lower_bound(xs.begin(),xs.end(),x)-xs.begin();
    40     }
    41 };
  • 相关阅读:
    第三十一章 线程------GIL、线/近程池、异/同步、异步回调
    第三十章 网路编程------线程
    第二十八章 网络编程------Socket
    第二十七章 网络编程
    第二十六章 oop中元类、异常处理
    第二十五章 面向对象------封装、内置函数、反射、动态导入
    第二十四章 面向对象------属性
    Document 对象
    正值表达式
    BOM和DOM
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14727887.html
Copyright © 2011-2022 走看看