Leetcode 第 173 场周赛 题解

Posted Asurudo Jyo の 倉 庫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode 第 173 场周赛 题解相关的知识,希望对你有一定的参考价值。

Leetcode 第173场周赛 题解

删除回文子序列

因为该字符串仅有两字符构成,且删的是子序列,不要求连续,所以不难想到:

  1. 若为空串,则答案为 (0)

  2. 若为回文串,则答案为 (1)

  3. 否则,一定可以先把 (b) 字符构成的子序列删除,再把 (a) 字符构成的子序列删除,答案为 (2)

时间复杂度 (O(n))

typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f3f3f3f3f
#define ZHUO 11100000007
#define SHENZHUO 1000000007
#define pb push_back
#define debug() printf("Miku Check OK!
")
#define maxn 200003
#define X first
#define Y second


class Solution
{
public:
    bool ispa(string s)
    {
        int sz = s.size();
        for(int i=0; i < sz ; i++)
        {
            if(s[i] != s[sz-i-1])
            {
                return false;
            }
        }
        return true;
    }
    int removePalindromeSub(string s)
    {
        if(s.empty())
            return 0;
        if(ispa(s))
            return 1;
        return 2;
    }
};

餐厅过滤器

小模拟题,没啥好说的,注意最后的排序规则即可。

时间复杂度 (O(nlogn))

typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f3f3f3f3f
#define ZHUO 11100000007
#define SHENZHUO 1000000007
#define pb push_back
#define debug() printf("Miku Check OK!
")
#define maxn 20003
#define X first
#define Y second


struct res
{
    int id;
    int rate;
    int vf;
    int pri;
    int dis;
    bool operator < (res b)
    {
        if(rate != b.rate)
            return rate > b.rate;
        return id > b.id;
    }
};
class Solution
{
public:
    vector<res> r;
    vector<int> filterRestaurants(vector<vector<int>>& restaurants, int veganFriendly, int maxPrice, int maxDistance)
    {
        int a = veganFriendly;
        int b = maxPrice;
        int c = maxDistance;
        vector<vector<int>> in = restaurants;
        _for(i,0,in.size())
        {
            if(a==0 || a==1 && in[i][2]==1)
            {
                if(in[i][3]<=b && in[i][4]<=c)
                    r.pb({in[i][0],in[i][1],in[i][2],in[i][3],in[i][4]});
            }
        }
        sort(r.begin(),r.end());
        vector<int> rnt;
        _for(i,0,r.size())
            rnt.pb(r[i].id);
        return rnt;
        
    }
};

阈值距离内邻居最少的城市

建图,每个点跑一遍单源最短路,我用的是优先队列(Dij) 。然后遍历所有点,超过阈值就 (++) ,最后统计一下最少的就行。

时间复杂度 (O(n^2logn))

typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f3f3f3f3f
#define ZHUO 11100000007
#define SHENZHUO 1000000007
#define pb push_back
#define debug() printf("Miku Check OK!
")
#define maxn 1003
#define X first
#define Y second

//最大点数
#define maxn 1003
//最大边数
#define maxe 20003

class Solution
{
    public:
    struct G
    {
        int n,m;
        int Next[maxe];
        int head[maxn];
        int ver[maxe];
        int val[maxe];
        int tot;
        void add(int x,int y,int w)
        {
            ver[++tot] = y,Next[tot] = head[x],head[x] = tot,val[tot] = w;
        }
} g;
    struct Dij
    {
        typedef pair<int,int> P;
        ll d[maxn];
        int vis[maxn];
        priority_queue<P,vector<P>,greater<P>> q;
        int s;
        void dij(int s,const G &g)
        {
            _for(i,1,g.n+1)
                d[i] = INF;
            memset(vis,0,sizeof(vis));
            d[s] = 0;
            q.push(P {0,s});
            while(!q.empty())
            {
                P p = q.top();
                q.pop();
                int x = p.second;
                if(vis[x]) continue;
                vis[x] = 1;
                for(int i = g.head[x]; i; i = g.Next[i])
                {
                    int y = g.ver[i];
                    int w = g.val[i];
                    if(d[y] > d[x] + w)
                    {
                        d[y] = d[x] + w;
                        q.push(P {d[y],y});
                    }
                }
            }
        }
    } d1;
    int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold)
    {
        g.n = n;
        _for(i,0,edges.size())
        {
            g.add(edges[i][0]+1,edges[i][1]+1,edges[i][2]);
            g.add(edges[i][1]+1,edges[i][0]+1,edges[i][2]);
        }
        int rnt = 0;
        int mintimes = INT_MAX;
        _for(i,0,n)
        {
            d1.dij(i+1,g);
            int tmptimes = 0;
            _for(j,0,n)
                if(d1.d[j+1]<=distanceThreshold)
                    tmptimes ++;
            if(tmptimes <= mintimes)
                mintimes = tmptimes,rnt = i;
        }
        return rnt;
    }
};

工作计划的最低难度

想完成第 (i) ,就要完成第 (j(0≤j < i)) ,也就是需要依次完成,问题可转化为对数组进行划分,每个子数组的最大值的和的最小值问题。 最多可以划分 (jobDifficulty.size()) 块,特判一下能否划分。

然后观察到每个工作和当前已划分敲定,则最小难度敲定,且满足最优子结构性可以由小问题转化为大问题,故设 (dp[i][j]) 表示对于已进行 (i) 个划分,当前已做到任务 (j) 时的最小花费。有 (dp) 转移方程如下

(dp[i][j]=min(dp[i][j],dp[i-1][k]+maxx[k+1][j])(0≤k≤j-1))

也就是说,当前想进行新的划分,划分完就划分了 (i) 次,所以由划分数 (i-1) 转移而来。其中数组 (maxx[i][j]) 的意思是数组 (jobDifficulty) 下标为 从 (i)(j) 的最大值,也就是要加上这次划分所产生的新花费。

初始状态 (dp[0][0]:=0) 表示还没开始遍历数组时的 (0) 次划分,自然代价是 (0) 。目标是 (dp[d][jobDifficulty.size()]) ,代表遍历到最后一个元素且有 (d) 次划分。

注意下标,时间复杂度 (O(dn^2))

typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f
#define ZHUO 11100000007
#define SHENZHUO 1000000007
#define pb push_back
#define debug() printf("Miku Check OK!
")
#define maxn 1003
#define X first
#define Y second

class Solution
{
public:
    vector<int> a;
    int rnt = INT_MAX;
    int dp[20][500];
    int maxx[500][500];
    int minDifficulty(vector<int>& jobDifficulty, int d)
    {
        a.pb(39);
        _for(i,0,jobDifficulty.size())
            a.pb(jobDifficulty[i]);
        int sz = a.size();
        if(d > sz-1)
            return -1;
            
        _for(i,1,sz)
        {
            int maxnow = a[i];
            _for(j,i,sz)
            {
                maxnow = max(maxnow,a[j]);
                maxx[i][j] = maxnow;
            }
        }
        
        memset(dp,INF,sizeof(dp));
        dp[0][0] = 0;

        _for(i,1,d+1)
            _for(j,1,sz)
                _for(k,0,j)
                    dp[i][j] = min(dp[i][j],dp[i-1][k]+maxx[k+1][j]);
        
        return dp[d][sz-1];
    }
};

以上是关于Leetcode 第 173 场周赛 题解的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 第174场周赛 题解

LeetCode地平线专场——第308场周赛题解

Leetcode第241场周赛题解+总结

Leetcode第240场周赛总结+题解

Leetcode第242场周赛总结+题解

Leetcode第239场周赛总结+题解