力扣第331场周赛题解
Posted hesorchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣第331场周赛题解相关的知识,希望对你有一定的参考价值。
rank | T1 | T2 | T3 | T4 |
---|---|---|---|---|
331 / 4256 | 0:01:46 | 0:06:18 (1) | 0:11:58 | 0:57:29 (4) |
T1 从数量最多的堆取走礼物
模拟题,每次操作找出最大值 m a x x maxx maxx并将其变成 s q r t ( m a x x ) sqrt(maxx) sqrt(maxx), k k k次操作后求和。
数据范围很小,可以暴力模拟,更好的方法是使用优先队列模拟。
时间复杂度
O
(
m
a
x
(
n
,
k
)
l
o
g
(
n
)
)
O(max(n,k)log(n))
O(max(n,k)log(n))
空间复杂度
O
(
n
)
O(n)
O(n)
参考代码
class Solution
public:
long long pickGifts(vector<int>& a, int k)
priority_queue<int> q;
for (auto it : a)
q.push(it);
while (k--)
int s = q.top();
q.pop();
s = sqrt(s);
q.push(s);
long long ans = 0;
while (q.size())
ans += q.top();
q.pop();
return ans;
;
T2 统计范围内的元音字符串数
给定一个字符串数组,每次询问区间 [ l , r ] [l,r] [l,r]内,首尾字母都是元音字母的字符串数量。
预处理前缀和,差分询问。
时间复杂度
O
(
n
+
q
)
O(n+q)
O(n+q)
空间复杂度
O
(
n
)
O(n)
O(n)
参考代码
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
class Solution
public:
map<int, int> mp;
bool check(string s)
return mp[s[0]] && mp[s.back()];
int sum[N];
vector<int> vowelStrings(vector<string>& a, vector<vector<int>>& q)
mp['a'] = 1;
mp['e'] = 1;
mp['i'] = 1;
mp['o'] = 1;
mp['u'] = 1;
int n = a.size();
for (int i = 0; i < n; i++)
sum[i + 1] = sum[i] + check(a[i]);
vector<int> ans;
for (auto it : q)
ans.emplace_back(sum[it[1] + 1] - sum[it[0]]);
return ans;
;
T3 打家劫舍 IV
要求最大值最小,经典二分答案+
c
h
e
c
k
check
check
c
h
e
c
k
check
check 思路:二分出
m
i
d
mid
mid,贪心地线性检查能否取出
k
k
k 个价值
<
=
m
i
d
<=mid
<=mid 的房屋即可。
时间复杂度
O
(
n
l
o
g
(
m
)
)
O(nlog(m))
O(nlog(m))
空间复杂度
O
(
n
)
O(n)
O(n)
参考代码
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
class Solution
public:
int minCapability(vector<int>& a, int k)
int n = a.size();
int l = 1, r = 1e9, ans;
while (l <= r)
int mid = (l + r) / 2;
int pre = -2;
int sum = 0;
for (int i = 0; i < n; i++)
if (i - pre == 1)
//不能相邻
continue;
if (a[i] <= mid)
//选择
sum++;
pre = i;
if (sum >= k)
r = mid - 1;
ans = mid;
else
l = mid + 1;
return ans;
;
T4 重排水果
如下考虑:
-
判断原数组是否合法:两个数组排序后相同,则直接返回0。
-
判断是否存在解:将两个数组的元素混合在一起,如果某个元素为奇数个,那么一定无解。
-
剩下来的是必定有解,但需要交换的情况。
首先去除他们的交集元素,现在数组 a a a 和数组 b b b 分别多了某些元素。根据每个元素的总数量,容易计算得到他们分别多出来 x i x_i xi 个 y i y_i yi,维护 o u t a outa outa和 o u t b outb outb, o u t a [ x ] = y outa[x]=y outa[x]=y表示数组 a a a的 x x x元素多了 y y y个。
考虑如何交换最优:
① 用数组 a a a中的最小值和数组 b b b中的最大值交换,花费为 m i n ( a m i n n , b m a x x ) min(a_minn,b_maxx) min(aminn,bmaxx)
② 用数组 a a a中的最大值和数组 b b b中的最小值交换,花费为 m i n ( b m i n n , a m a x x ) min(b_minn,a_maxx) min(bminn,amaxx)
③ 容易遗漏的一种情况,利用所有元素的最小值作为中间者,间接的交换 a b ab ab中的元素:swap(a,c); swap(b,c);
,因为 c c c必定为最小值,且被用到了两次,因此花费为 m i n n ∗ 2 minn*2 minn∗2
贪心地,如果数组 a a a中的最小值 < < <数组 b b b中的最小值,则选用方案①③的组合,否则选用方案②③的组合。
时间复杂度
O
(
n
l
o
g
(
n
)
)
O(nlog(n))
O(nlog(n))
空间复杂度
O
(
n
)
O(n)
O(n)
参考代码
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
class Solution
public:
long long minCost(vector<int>& a, vector<int>& b)
int MINN = INF;
map<int, int> mp, ma, mb;
for (auto it : a)
mp[it]++, ma[it]++;
MINN = min(MINN, it);
for (auto it : b)
mp[it]++, mb[it]++;
MINN = min(MINN, it);
if (ma == mb)
// 已经合法
return 0;
for (auto& it : mp)
if (it.second % 2)
// 某个元素总数量奇数个,不能平分
return -1;
// 期望每个数组各有it.second个it.first
it.second /= 2;
vector<pair<int, int>> outa, outb;
int all = 0;
for (auto it : mp)
int delta = ma[it.first] - it.second;
// a中需要给出delta个it.first
if (delta > 0)
// 总共需要给出all个
all += delta;
outa.emplace_back(make_pair(it.first, delta));
delta = mb[it.first] - it.second;
// b中需要给出delta个it.first
if (delta > 0)
outb.emplace_back(make_pair(it.first, delta));
long long ans = 0;
int n = outa.size();
int ra = outa.size() - 1;
int rb = outb.size() - 1;
int la = 0;
int lb = 0;
while (all--)
if (!outa[la].second)
++la;
if (!outa[ra].second)
--ra;
if (!outb[lb].second)
++lb;
if (!outb[rb].second)
--rb;
if (outa[la].first < outb[lb].first)
outa[la].second--;
outb[rb].second--;
// 两种情况,借助最小值来间接交换 / 直接交换
ans += min(min(MINN * 2, outa[la].first), outb[rb].first);
if (outa[la].first > outb[lb].first)
outa[ra].second--;
outb[lb].second--;
ans += min(min(MINN * 2, outa[ra].first), outb[lb].first);
return ans;
;
以上是关于力扣第331场周赛题解的主要内容,如果未能解决你的问题,请参考以下文章