Leetcode 第 173 场周赛 题解(完结)
Leetcode 第173场周赛 题解
删除回文子序列
因为该字符串仅有两字符构成,且删的是子序列,不要求连续,所以不难想到:
-
若为空串,则答案为 \(0\)
-
若为回文串,则答案为 \(1\)
-
否则,一定可以先把 \(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];
}
};