第一题比较简单,排个序后开个哈希表存总和就行
class Solution {
public:
int distinctAverages(vector<int>& nums) {
unordered_set<int> hash;
sort(nums.begin(), nums.end());
for(int i = 0, j = nums.size() - 1; i < j; i ++ , j --)
hash.insert(nums[i] + nums[j]);
return hash.size();
}
};
T2:LeetCode 2466. 统计构造好字符串的方案数
简单dp问题
就表示长度为 的字符串有多少个,我们可以将分为两类:
一类是以one个1结尾,那我们就只要统计
另一类是以zero个0结尾,同理我们就只要统计
所以最后
class Solution {
public:
int countGoodStrings(int low, int high, int zero, int one) {
const int MOD = 1e9 + 7;//先定义个取模数
vector<int> f(high + 1);
f[0] = 1;//初始一个都没有也是个方案
int res = 0;
for(int i = 1; i <= high; i ++ )
{
if(i >= zero) f[i] = f[i - zero];
if(i >= one) f[i] = (f[i] + f[i - one]) % MOD;
if(i >= low) res = (res + f[i]) % MOD;
}
return res;
}
};
无向树
先分析一下题意:
Alice不断向下的路径并不是唯一的。
我们可以发现Bob每次走的路径是唯一的,我们是可以知道Bob每次走到哪里的,那这样我们就可以预处理一下每个点Bob到达的时间,根据样例给出个图
Bob从0那一点开始走,一直往上
然后我们看看Alice是怎么走的
首先Alice从根节点下来,之后开始分叉。
可以看出Alice能得到的分值是唯一确定的,不管是往左右走,左走的话不用说,右走的话也是唯一确定的只是有了Bob的影响不好算,但也还是唯一确定的。
所以我们就可以算出Alice往左右走的分值最大的是多少,所以Alice走的路径的话就是每次取最大的儿子方向走就可以了,难点就在算Alice的分数
接下来分析一下,如何算Alice的分数
在这里我们用At表示Alice到达的时间,Bt表示Bob到达的时间。
下面在代码中展示吧
const int N = 100010, M = N * 2;
int n;
int h[N], w[N], e[M], ne[M], idx;
int bt[N], p[N];
class Solution {
public:
void add(int a, int b)//建立一个无向图,加边函数
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs1(int u, int fa)
{
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(j == fa) continue;
p[j] = u;
dfs1(j, u);
}
}
int dfs2(int u, int fa, int t)
{
int val = 0;//权值
//这里分类讨论
if(bt[u] == -1 || t < bt[u]) val = w[u];
else if(t == bt[u]) val = w[u] / 2;
int mx = -2e9;//定义最大值
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
mx = max(mx, dfs2(j, u, t + 1));
}
if(mx == -2e9) mx = 0;//没有儿子,没有儿子结点
return val + mx;//返回答案
}
int mostProfitablePath(vector<vector<int>>& edges, int bob, vector<int>& amount) {
memset(h, -1, sizeof h);
idx = 0;
n = amount.size();
for(int i = 0; i < n; i ++ ) w[i] = amount[i];//求权值
for(auto& edge: edges){//加边
int a = edge[0], b = edge[1];
add(a, b), add(b, a);
}
dfs1(0, -1);//这里直接枚举每个点的父节点
memset(bt, -1, sizeof bt);//每个点到达的时间都初始化成-1
int t = 0;
while(true)
{
bt[bob] = t;//每次往上走一个就 ++
t ++ ;
if(!bob) break;
bob = p[bob];//bob要走到父节点的位置
}
return dfs2(0, -1, 0);
}
};
推公式:
class Solution {
public:
int get(int k, int limit)
{
int len = to_string(k).size();
int res = (limit - 3 - len) * k;
int s = 0;
for(int i = 1, t = 9; i < len; i ++, t *= 10)
{
res -= i * t;
s += t;
}
res -= len * (k - s);
return res;
}
vector<string> splitMessage(string message, int limit) {
int n = message.size();
for(int i = 1; i <= n; i ++ ){
if(get(i, limit) >= n){
vector<string> res;
for(int j = 1, k = 0; j <= i && k < n; j ++ ){
string str = "<" + to_string(j) + "/" + to_string(i) + ">";
int len = min(n - k, limit - (int)str.size());
res.push_back(message.substr(k, len) + str);
k += len;
}
return res;
}
}
return {};
}
};