翻转成“先0后1的数”的minFlips
可用动态规划
int minFlipsMonoIncr(string S) {
// 设子问题S[0..i]以'0'结尾时minFlips为dp[i][0],以'1'结尾时minFlips为dp[i][1]
// dp[i][0] = dp[i-1][0] + (S[i]=='1')
// dp[i][1] = min(dp[i-1][0], dp[i-1][1]) + (S[i]=='0')
// 递推式在i这维上只依赖i-1项,省掉i这维:
// dp[1] = min(dp[0], dp[1]) + (S[i]=='0')
// dp[0] += (S[i]=='1') // dp[0]覆盖放后面
int f0 = 0, f1 = 0;
for (char c : S) {
f1 = min(f0, f1) + (c == '0');
f0 += (c == '1');
}
return min(f0, f1);
}
也可用前缀后缀数组
int minFlipsMonoIncr(string S) {
const int N = S.size();
vector<int> pre(N + 1); // pre[i]表示S[..i-1]以0结尾
for (int i = 0; i < N; i++) {
pre[i+1] = pre[i] + (S[i] == '1');
}
vector<int> suf(N + 1); // suf[i]表示S[i..]以1开头
for (int i = N - 1; i >= 0; i--) {
suf[i] = suf[i+1] + (S[i] == '0');
}
int ans = INT_MAX;
for (int i = 0; i <= N; i++) {
ans = min(ans, pre[i] + suf[i]);
}
return ans;
}
山峰数组
int longestMountain(vector<int>& A) {
const int N = A.size();
vector<int> inc(N), dec(N);
for (int i = 1; i < N; i++) {
if (A[i] > A[i-1])
inc[i] = inc[i-1] + 1;
}
for (int i = N - 2; i >= 0; i--) {
if (A[i] > A[i+1])
dec[i] = dec[i+1] + 1;
}
int ans = 0;
for (int i = 1; i < N - 1; i++) {
if (inc[i] && dec[i])
ans = max(ans, inc[i] + dec[i] + 1);
}
return ans;
}
也可一遍扫描统计
int longestMountain(vector<int>& A) {
// 统计一段上升和下降的最大长度
int up = 0, down = 0, ans = 0;
for (int i = 1; i < A.size(); i++) {
if (A[i] > A[i-1]) {
if (down > 0) up = down = 0; // 下降结束,开始新一段的统计
up++;
} else if (A[i] < A[i-1]) {
down++;
} else {
up = down = 0; // 开始新一段的统计
}
if (up > 0 && down > 0) {
ans = max(ans, 1 + up + down); // 1来自统计开始处的元素
}
}
return ans;
}
各项为除了自己外的数组乘积
vector<int> productExceptSelf(vector<int>& nums) {
const int N = nums.size();
vector<int> ans(N, 1);
// 从左到右扫一遍
for (int i = 0, prodL = 1; i < N; i++) {
ans[i] *= prodL;
prodL *= nums[i];
}
// 从右到左扫一遍
for (int i = N - 1, prodR = 1; i >= 0; i--) {
ans[i] *= prodR;
prodR *= nums[i];
}
return ans;
}