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];
	}
};
posted @ 2020-01-26 13:01  Asurudo  阅读(254)  评论(0编辑  收藏  举报