题目链接
题目描述
小红定义一个数组为好数组当且仅当这个数组至少存在一个长度为3的非降序子数组。小红可以进行多次操作,每次操作可以修改数组中的一个元素。小红想知道至少需要操作几次才可以把这个数组变成不是好数组。
输入:
- 第一行输入一个整数
,表示数组的长度
- 第二行输入
个整数
,表示数组的初始值
输出:
- 一个整数,表示最少需要的操作次数
解题思路
这是一个贪心问题,可以通过以下步骤解决:
-
关键发现:
- 要使数组不是好数组,就要破坏所有长度为3的非降序子数组
- 对于连续的三个数 a[i-1], a[i], a[i+1]:
- 如果 a[i] >= a[i-1] 且 a[i] <= a[i+1],这就是一个非降序子数组
- 我们必须修改中间的数 a[i] 来破坏这个非降序关系
- 修改完一个位置后,可以跳过下一个位置(因为已经破坏了包含它的所有长度为3的非降序子数组)
-
贪心策略:
- 从左到右遍历数组
- 当找到一个非降序的三元组时:
- 修改中间的数
- 跳过下一个位置(因为已经不可能形成非降序子数组)
- 统计需要修改的次数
-
具体步骤:
- 遍历数组中的每个位置 i(从1到n-2)
- 检查 a[i-1], a[i], a[i+1] 是否构成非降序
- 如果是,则需要修改 a[i],并跳过 i+1
代码
#include <bits/stdc++.h>
using ll = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
for (int &x : a) {
std::cin >> x;
}
std::vector<int> b(n);
int ans = 0;
for (int i = 1; i < n - 1; i++) {
if (a[i] >= a[i - 1] && a[i] <= a[i + 1]) {
ans++;
i += 1; // 跳过下一个位置
}
}
std::cout << ans << "\n";
return 0;
}
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] a = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i < n; i++) {
a[i] = Integer.parseInt(st.nextToken());
}
int ans = 0;
for(int i = 1; i < n - 1; i++) {
if(a[i] >= a[i - 1] && a[i] <= a[i + 1]) {
ans++;
i++; // 跳过下一个位置
}
}
System.out.println(ans);
}
}
import sys
input = sys.stdin.readline
n = int(input())
a = list(map(int, input().split()))
ans = 0
i = 1
while i < n - 1:
if a[i] >= a[i - 1] and a[i] <= a[i + 1]:
ans += 1
i += 2 # 跳过下一个位置
else:
i += 1
print(ans)
算法及复杂度
- 算法:贪心
- 时间复杂度:
- 只需要遍历一次数组
- 空间复杂度:
- 需要存储输入数组