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!\n")
#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!\n")
#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!\n")
#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!\n")
#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];
    }
};

猜你喜欢

转载自www.cnblogs.com/Asurudo/p/12234095.html