元素和最小的山形三元组 II
预处理前缀和后缀最小值,记为pre[i]和sa[i]
对于当前编号i,如果前面的最小值和后面的最大值都小于nums[i],则记录ans[i] = nums[i]+pre[i-1]+sa[i+1]
结果输出最小的ans[i]即可。
合法分组的最少组数
统计每一个数字出现的次数。将每一个数字分为大小为
d
d
d或
d
+
1
d+1
d+1的组,令
d
d
d尽可能大。
d
d
d不满足单调性,不好二分。思路时直接暴力。
计最小出现次数为
m
n
mn
mn,出现过的数字个数为
c
n
t
cnt
cnt,显然有
m
n
∗
c
n
t
≤
n
u
m
s
.
l
e
n
g
t
h
mn*cnt \le nums.length
mn∗cnt≤nums.length
而显然有
d
+
1
≤
m
n
d+1 \le mn
d+1≤mn,因此直接枚举d
对于某个数字i,其出现次数为
t
o
t
i
tot_i
toti,若
d
d
d成立则需要满足存在x令
x
d
≤
t
o
t
i
≤
x
(
d
+
1
)
xd \le tot_i \le x(d+1)
xd≤toti≤x(d+1)
令
x
=
t
o
t
i
/
d
x = tot_i/d
x=toti/d,即以
d
d
d为标准将
t
o
t
i
tot_i
toti分为x组,此时还剩
t
o
t
i
%
d
tot_i\%d
toti%d个元素,每一组中最多可以容纳
d
+
1
d+1
d+1个元素,最多可以容纳x个元素,使x组的个数都变为%d+1%。因此只要满足
t
o
t
i
%
d
≤
x
tot_i\%d \le x
toti%d≤x即
t
o
t
i
%
d
≤
t
o
t
i
/
d
tot_i\%d \le tot_i/d
toti%d≤toti/d,则对数字
i
i
i而言
d
d
d是合法的分组。
已知d,数字i的分组个数为
t
o
t
i
+
d
m
n
+
1
\frac{tot_i+d}{mn+1}
mn+1toti+d。
x
x
x需要取最小值满足
x
d
≤
t
o
t
i
≤
x
(
d
+
1
)
xd \le tot_i \le x(d+1)
xd≤toti≤x(d+1),有
⌈
t
o
t
i
/
(
d
+
1
)
⌉
≤
x
\lceil tot_i/(d+1)\rceil \le x
⌈toti/(d+1)⌉≤x,因此取
x
=
⌈
t
o
t
i
d
+
1
⌉
x =\lceil \frac{tot_i}{d+1}\rceil
x=⌈d+1toti⌉
枚举
d
d
d,计算分组个数,求分组最小值即可,复杂度为
O
(
m
n
∗
c
n
t
)
O(mn*cnt)
O(mn∗cnt)
得到 K 个半回文串的最少修改次数
数据只有200,想法是纯暴力
令
M
i
n
T
i
m
e
s
[
i
]
[
j
]
MinTimes[i][j]
MinTimes[i][j]为子串
s
t
r
i
j
str_{ij}
strij变成半回文串最少的次数,暴力计算,复杂度为
O
(
n
4
)
O(n^4)
O(n4)
令dp[i][j]为以
s
t
r
i
str_i
stri为结尾时分为
j
j
j段最少的操作次数
d
p
[
i
]
[
j
]
=
min
d
p
[
z
]
[
j
−
1
]
+
M
i
n
T
i
m
e
s
[
z
+
1
]
[
i
]
dp[i][j] = \min dp[z][j-1]+MinTimes[z+1][i]
dp[i][j]=mindp[z][j−1]+MinTimes[z+1][i]
总复杂度
O
(
n
4
)
O(n^4)
O(n4)
计算MinTimes时可以将一个n优化成
n
\sqrt n
n甚至预处理成
lg
n
\lg n
lgn,但是
O
(
n
4
)
O(n^4)
O(n4)也能过就是了,大概是数据比较弱吧
class Solution {
public:
int MinTimes[210][210];
int dp[210][210];
int calTimes(string &s,int l,int r)
{
int ret = (1<<30);
int len = r-l+1;
while(--len)
{
if((r-l+1)%len)
continue;
int ans = 0;
for(int i=0;i<len;++i)
{
string t1;
for(int j=l+i;j<=r;j+=len)
t1 += s[j];
for(int c=0;c<t1.size()/2;++c)
if(t1[c]!=t1[t1.size()-1-c])
ans++;
}
ret = min(ret,ans);
}
return ret;
}
int minimumChanges(string s, int k) {
memset(dp,0x3f,sizeof(dp));
dp[0][0] = 0;
int l = s.size();
for(int i=0;i<l;++i)
{
for(int j=i+1;j<l;++j)
{
MinTimes[i][j] = calTimes(s,i,j);
}
MinTimes[i][i] = (1<<30);
}
for(int i=0;i<l;++i)
{
for(int j=0;j<=i;++j)
{
for(int z=1;z<=k;++z)
{
dp[i+1][z] = min(dp[i+1][z],dp[j][z-1]+MinTimes[j][i]);
}
}
}
return dp[l][k];
}
};