2021-02-14 第 228 场周赛
1758. 生成交替二进制字符串的最少操作数
思路1:动态规划,dp[i][j]
表示前i个字符串成为交替二进制字符串,并且最后一位为j的最少操作数,那么状态转移方程为:
d
p
[
i
]
[
0
]
=
d
p
[
i
−
1
]
[
1
]
+
(
s
[
i
]
=
=
′
0
′
?
0
:
1
)
dp[i][0] = dp[i-1][1] + (s[i] == '0' ? 0 : 1)
dp[i][0]=dp[i−1][1]+(s[i]==′0′?0:1)
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + ( s [ i ] = = ′ 1 ′ ? 0 : 1 ) (2) dp[i][1] = dp[i-1][0] + (s[i] == '1' ? 0 : 1) \tag{2} dp[i][1]=dp[i−1][0]+(s[i]==′1′?0:1)(2)
class Solution {
public int minOperations(String _s) {
char[] s = _s.toCharArray();
int n = s.length;
int[][] dp = new int[n][2];
dp[0][0] = (s[0] == '0') ? 0 : 1;
dp[0][1] = (s[0] == '1') ? 0 : 1;
for(int i = 1;i < n;i++) {
for(int j = 0;j < 2;j++) {
int cost = (s[i] == (j + '0')) ? 0 : 1;
dp[i][j] = dp[i-1][j^1] + cost;
}
}
return Math.min(dp[n-1][0], dp[n-1][1]);
}
}
思路2:题解区中的一种比较巧妙的思路,因为交替字符串只有两种情况,所以可以分类讨论
1.偶数位为0,奇数位为1
这种情况下,任意位的值和索引奇偶性相同,即s[i]%2==i%2
,若不满足,即需要变动该位,则计数cnt1++
2.偶数位为1,奇数位为0
这种情况下,任意位的值和索引奇偶性不同,即s[i]%2!=i%2
,若不满足,即需要变动该位,则计数cnt2++
比较哪种需要变动的次数小即可。
class Solution {
public int minOperations(String _s) {
char[] s = _s.toCharArray();
int n = s.length, cnt1 = 0, cnt2 = 0;
for(int i = 0;i < n;i++) {
int v = s[i] - '0';
if(v % 2 != i % 2) {
cnt1++;
} else {
cnt2++;
}
}
return Math.min(cnt1, cnt2);
}
}
1759. 统计同构子字符串的数目
思路:简单来说就是统计连续字符串出现的个数,如果连续出现了n次,那么结果就加上(n+1)*n/2。
class Solution {
int mod = (int) (1e9 + 7);
public int countHomogenous(String _s) {
char[] s = _s.toCharArray();
long res = 0, cur = 1;
char last = '#';
for(char ch : s) {
if(ch == last) {
cur++;
} else {
last = ch;
cur = 1;
}
res += cur;
res %= mod;
}
return (int) res;
}
}
1760. 袋子里最少数目的球
思路:典型的二分题,难点就在于如何计算将一个数num
分为不超过mx
,所需要的次数。
可以这样想,先计算需要将num
分为多少堆,堆数piles
的计算公式为Math.ceil(1.0*num/mx)
。由于每次操作都会使得现有的堆数加1,而只有一个数字的时候堆数为1,所以操作数为piles-1
。
class Solution {
public boolean check(int[] nums, int mx, int maxOperations) {
int cnt = 0;
for(int num : nums) {
int piles = num / mx + (num % mx == 0 ? 0 : 1) ;
cnt += piles - 1;
}
return cnt <= maxOperations;
}
public int minimumSize(int[] nums, int maxOperations) {
int l = 1, r = (int) 1e9;
while(l <= r) {
int mid = (l+r) >> 1;
if(check(nums, mid, maxOperations)) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l;
}
}
1761. 一个图中连通三元组的最小度数
思路:暴力,枚举三元组,然后计算当前三元组的度数即可。
class Solution {
public int minTrioDegree(int n, int[][] edges) {
int[][] arr = new int[n+1][n+1];
int[] d = new int[n+1];
int res = -1;
for(int[] e:edges) {
arr[e[0]][e[1]] = 1; arr[e[1]][e[0]] = 1;
d[e[0]]++; d[e[1]]++;
}
for(int i = 1;i <= n;i++) {
for(int j = i+1;j <= n;j++) {
for(int k = j+1;k <= n;k++) {
if(arr[i][j] == 1 && arr[i][k] == 1 && arr[j][k] == 1) {
int degree = d[i] + d[j] + d[k] - 6;
if(res == -1 || res > degree) {
res = degree;
}
}
}
}
}
return res;
}
}