【华为OD-E卷-简单的自动曝光 100分(python、java、c++、js、c)】
题目
一个图像有n个像素点,存储在一个长度为n的数组img里,每个像素点的取值范围[0,255]的正整数。
请你给图像每个像素点值加上一个整数k(可以是负数),得到新图newImg,使得新图newImg的所有像素平均值最接近中位值128。
请输出这个整数k
输入描述
- n个整数,中间用空格分开
输出描述
- 一个整数k
备注
- 1 <= n <= 100 如有多个整数k都满足,输出小的那个k; 新图的像素值会自动截取到[0,255]范围。当新像素值<0,其值会更改为0;当新像素值>255,其值会更改为255; 例如newImg="-1 -2 256″,会自动更改为"0 0 255″
用例
用例一:
输入:
0 0 0 0
输出:
128
用例二:
输入:
129 130 129 130
输出:
-2
python解法
- 解题思路:
- 目标:找到一个调整值 k,使得对图像像素值进行调整后,像素值的平均值尽量接近128(即接近中值区域)。
像素值调整规则:
每个像素值 p 在调整后需满足范围约束 [0, 255]。
调整公式为:adjusted_img = [max(0, min(255, p + k)) for p in img]。
搜索范围:
k 在范围 [-127, 128] 内搜索。
优化准则:
优先使调整后的像素值平均值与128的绝对差值最小。
如果差值相等,选择较小的 k。
最终返回:
最优调整值 k。
python
def closest_to_median(img):
# 初始化最优的调整值和最小差值
best_k = None
min_diff = float('inf')
# 遍历可能的调整值k,范围是[-127, 128]
for k in range(-127, 129):
# 调整像素值,确保结果在[0, 255]范围内
adjusted_img = [max(0, min(255, p + k)) for p in img]
# 计算调整后的像素值的平均值
avg_val = sum(adjusted_img) / len(img)
# 计算平均值与目标128的绝对差值
diff = abs(avg_val - 128)
# 如果当前调整后的差值更小,或者在差值相等时k更小,则更新最优解
if diff < min_diff or (diff == min_diff and (best_k is None or k < best_k)):
min_diff = diff
best_k = k
# 返回最优调整值
return best_k
# 读取像素值作为输入
pixels = list(map(int, input().split()))
# 输出计算出的最优调整值
print(closest_to_median(pixels))
java解法
- 解题思路
- 目标:找到一个调整值 k,使对像素值调整后,像素值的平均值尽可能接近128。
调整规则:
每个像素值 pixel 被调整为 newVal = max(0, min(255, pixel + k))。
调整后需满足范围 [0, 255]。
二分搜索:
利用二分搜索的思想在 k ∈ [-127, 128] 范围内搜索。
对每个中间值 mid,计算调整后的平均值 currentAvg。
根据 currentAvg 与128的差异更新最优调整值 bestK。
如果 currentAvg < 128,说明需要增大 k,否则需要减小 k。
最终返回:
找到的最优调整值 k。
java
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取输入的像素值,以空格分隔
String str = sc.nextLine();
int[] pixels = Arrays.stream(str.split(" ")).mapToInt(Integer::parseInt).toArray();
// 输出最优的调整值 k
System.out.println(findBestK(pixels));
}
// 找到使调整后平均值最接近128的最佳k值
public static int findBestK(int[] pixels) {
int left = -127, right = 128; // 搜索范围
int bestK = 0; // 记录当前最佳的k值
double bestDiff = Double.MAX_VALUE; // 当前最小的与128的差异
// 二分搜索
while (left <= right) {
int mid = (left + right) / 2; // 计算中间值k
double currentAvg = calculateAvg(pixels, mid); // 计算调整后的平均值
// 计算当前调整值与目标128的绝对差
double diff = Math.abs(currentAvg - 128);
// 更新最优k值,如果差值更小,或者在差值相等时k更小
if (diff < bestDiff || (diff == bestDiff && mid < bestK)) {
bestDiff = diff;
bestK = mid;
}
// 根据调整后的平均值与128的大小关系调整搜索范围
if (currentAvg < 128) {
left = mid + 1; // 平均值小于128,增加k
} else {
right = mid - 1; // 平均值大于等于128,减小k
}
}
return bestK; // 返回最佳k值
}
// 计算调整后的平均值
public static double calculateAvg(int[] pixels, int k) {
double sum = 0;
// 遍历所有像素值,进行调整并计算总和
for (int pixel : pixels) {
int newVal = Math.max(0, Math.min(pixel + k, 255)); // 确保调整后的值在[0, 255]范围内
sum += newVal;
}
// 返回调整后的平均值
return sum / pixels.length;
}
}
C++解法
- 解题思路
cpp
更新中
C解法
解题思路
c
更新中
JS解法
解题思路
-
目标: 找到一个调整值 k,使调整后的数组中所有像素值的平均值尽可能接近 128。
像素值调整规则:
每个像素值 arr[i] 被调整为 newVal = Math.min(255, Math.max(0, arr[i] + k)),确保调整后的像素值在 [0, 255] 范围内。
搜索范围:
使用二分搜索在 [-127, 128] 范围内寻找最优的调整值 k。
优化准则:
目标是让调整后数组的平均值与128的绝对差值最小。
如果差值相等,选择较小的 k。
二分搜索过程:
计算当前中间值 mid 的调整后平均值与128的差异。
根据与128的关系调整搜索范围。
最终返回:
找到的最优调整值 k。
javascript
const readline = require("readline");
// 创建命令行接口,监听输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 监听每行输入
rl.on("line", (line) => {
// 将输入的字符串转为整数数组
const arr = line.split(" ").map(Number);
// 调用函数计算最优调整值k并输出
console.log(findOptimalK(arr));
});
// 主函数:找到最优的调整值k
function findOptimalK(arr) {
let left = -127, right = 128; // 二分搜索范围
let bestK = 0, bestDiff = Infinity; // 最优k值和当前最小差值
// 二分搜索
while (left <= right) {
let mid = Math.floor((left + right) / 2); // 计算当前中间值
const diffMid = calculateDiff(arr, mid); // 当前k对应的绝对差
// 如果当前差值更小,更新最优k值;如果差值相等,选择较小的k
if (diffMid < bestDiff) {
bestDiff = diffMid;
bestK = mid;
} else if (diffMid === bestDiff) {
bestK = Math.min(bestK, mid);
}
// 调整搜索范围,根据左右相邻差值大小进行移动
if (calculateDiff(arr, mid - 1) < diffMid) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return bestK; // 返回最优k值
}
// 辅助函数:计算调整后与128的绝对差
function calculateDiff(arr, k) {
let sum = 0;
// 遍历数组,对每个像素值进行调整
for (let i = 0; i < arr.length; i++) {
let newVal = arr[i] + k; // 调整像素值
newVal = newVal < 0 ? 0 : newVal > 255 ? 255 : newVal; // 确保调整后的值在[0, 255]范围内
sum += newVal; // 累加调整后的像素值
}
// 返回调整后平均值与128的绝对差
return Math.abs(sum / arr.length - 128);
}
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏