题解:好等差数列
源题目地址:www.lanqiao.cn/problems/22…
问题描述
给定一个长度为n的数列,进行m次修改操作,每次修改后需要计算当前数列到"好等差数列"的距离。"好等差数列"是指公差为整数的等差数列,距离定义为最少需要修改的元素数量使数列变为好等差数列。
解题思路
- 暴力枚举:对于每次修改后的数列,枚举所有可能的公差情况
- 频率统计:统计相同元素的数量(公差为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));
PrintWriter pw = new PrintWriter(System.out);
// 读取输入
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 m = Integer.parseInt(br.readLine());
List<Integer> results = new ArrayList<>();
// 处理每次修改
for (int k = 0; k < m; k++) {
st = new StringTokenizer(br.readLine());
int p = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
a[p] = v; // 执行修改
results.add(calculateDistance(a, n));
}
// 输出结果
StringBuilder sb = new StringBuilder();
for (int i = 0; i < results.size(); i++) {
sb.append(results.get(i));
if (i < results.size() - 1) sb.append(" ");
}
pw.println(sb.toString());
pw.close();
br.close();
}
// 计算数列到好等差数列的距离
private static int calculateDistance(int[] a, int n) {
if (n <= 1) return 0; // 长度≤1的数列本身就是等差数列
int maxMatches = 0;
// 情况1:公差为0(所有元素相同)
Map<Integer, Integer> freqMap = new HashMap<>();
for (int val : a) {
freqMap.put(val, freqMap.getOrDefault(val, 0) + 1);
}
for (int count : freqMap.values()) {
maxMatches = Math.max(maxMatches, count);
}
// 情况2:公差不为0
for (int i = 0; i < n; i++) {
Map<Integer, Integer> diffCounts = new HashMap<>();
for (int j = i + 1; j < n; j++) {
long diffVal = (long)a[j] - a[i]; // 使用long防止溢出
int diffIdx = j - i;
// 检查是否为整数公差
if (diffVal % diffIdx == 0) {
int d = (int)(diffVal / diffIdx);
diffCounts.put(d, diffCounts.getOrDefault(d, 0) + 1);
}
}
// 更新最大匹配数
for (int count : diffCounts.values()) {
maxMatches = Math.max(maxMatches, count + 1); // 包括当前元素i
}
}
return n - maxMatches; // 距离=总长度-最大匹配数
}
}
关键点说明
- 输入处理:使用BufferedReader高效读取输入数据
- 修改操作:直接修改数组元素并立即计算距离
- 距离计算:
- 统计相同元素数量(公差为0)
- 枚举所有可能的整数公差
- 计算每种公差下的匹配元素数量
- 结果输出:使用StringBuilder高效构建输出字符串
复杂度分析
- 时间复杂度:O(m*n²),其中n是数列长度,m是修改次数
- 空间复杂度:O(n),用于存储数列和中间结果
该解法通过暴力枚举和频率统计,能够正确处理小规模数据(n≤1000),但对于更大规模的数据可能需要更优化的算法。