题目部分
题目 | 简单的自动曝光 |
难度 | 易 |
题目说明 | 一个图像有 n 个像素点,存储在一个长度为n的数组img里,每个像素点的取值范围 [0,255] 的正整数。 请你给图像每个像素点值加上一个整数k(可以是负数),得到新图newlmg,使得新图newImg的所有像素平均值最接近中位值128。 请输出这个整数k。 |
输入描述 | n个整数,中间用空格分开。 例如: 0 0 0 0 4个数值,中间用空格分开。 |
输出描述 | 一个整数 k 。 |
补充说明 | 1<=n<=100; 如有多个整数k都满足,输出小的那个k; 新图的像素值会自动截取到[0,255]范围。当新像素值<0,其值会更改为0:当新像 素值>255,其值会更改为255; 例如newlmg="-1 -2 256",会自动更改为"0 0 255"。 |
------------------------------------------------------ | |
示例 | |
示例1 | |
输入 | 0 0 0 0 |
输出 | 128 |
说明 | 四个像素值都为0。 |
示例2 | |
输入 | 129 130 129 130 |
输出 | -2 |
说明 | -1 的均值是 128.5,-2 的均值是 127.5,输出较小的数 -2。 |
解读与分析
题目解读:
题目题目给出一系列初始整数值,取值范围 [ 0, 255 ]。要求给一个整数 k (可以为负数),与这一系列整数数相加(需要注意的是:当相加的结果小于或等于 0 时,取值为 0;当相加结果大于 255 时,取值为 255),使这一系列数字的平均值接近 128。
如果存在多个整数满足条件,则输出较小的那个值。
分析与思路:
此题中,这一系列整数的个数不超过 100。
思路非常简单,直接把 k 的值设为 -255 开始, 逐个与整数相加,小于 0 则取 0,大于 255 则取 255,求和之后,求平均值,计算平均值与 128 差值的绝对值。
然后 k 加 1(为 -254),继续进行上面的操作求平均值,直至 k 的最大值 255 求完平均值。最后,首次出现的绝对值,即为所求的 k。
在这个思路中,有 2 点可以优化:
1. k 的取值范围。刚才的思路中,k 的取值范围是[ -255, 255 ]。最终要求所有数字的平均值接近 128。我们思考一下,原始数字最大和最小的边界条件。显然,当 n 个数全为 255 时,平均值最大,此时 k 为 -127,即可保证所有数字平均值为128;当 n 个数全为 0 ,它们平均值最小,此时 k 为 128,即可保证所有数字平均值为 128 。显然,k 的取值范围可以缩小为 [ -127, 128 ]。
2. 平均值计算。在上面算法中,我们把所有数字求和,接着除以 n 求平均值,然后计算与 128 差值的绝对值。在除以 n 的时候,可能存在小数。而小数的计算可能存在误差,造成数字不准确的额情况。为了避免误差,我们可以在求和(假设和为 sum)之后,计算 | sum - 128 * n | ,保证它为最小值。稍加说明,n 的最大值为 100,使用 int 整形可满足取值范围。
上面的算法在[ -127, 128 ]范围内,让 k 逐次和 n 个数做加法。在最坏的情况下,共需要计算 256 * n 次。
代码实现
Java代码
import java.util.Scanner;/*** 简单的自动曝光* @since 2023.09.09* @version 0.1* @author Frank**/
public class ImgPixelChange {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String input = sc.nextLine();String[] strNumbers = input.split( " " );int[] numbers = convertStrNumbers2Int( strNumbers);processImgPixelChange( numbers );}}private static int[] convertStrNumbers2Int( String[] numbers){int[] ret = new int[numbers.length];for( int i = 0; i < numbers.length; i ++ ){ret[i] = Integer.parseInt( numbers[i] );}return ret;}private static void processImgPixelChange( int numbers[] ){int minDiff = Integer.MAX_VALUE;int AVERAGE_VALUE = 128 * numbers.length;int finalK = -127;for( int k = -127; k <= 128; k ++ ){int sum = 0;for( int i = 0; i < numbers.length; i ++ ){int tmpNumber = numbers[i] + k;if( tmpNumber < 0 ){tmpNumber = 0;}else if( tmpNumber > 255 ){tmpNumber = 255;}sum += tmpNumber;}int diff = Math.abs( sum - AVERAGE_VALUE );if( diff < minDiff ){minDiff = diff;finalK = k;}} System.out.println( finalK );}
}
JavaScript代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {while (line = await readline()) {var strNumbers = line.split(" ");var numbers = convertStrNumbers2Int(strNumbers);processImgPixelChange(numbers);}
}();function convertStrNumbers2Int( numbers) {var ret = new Array(numbers.length );for ( var i = 0; i < numbers.length; i++) {ret[i] = parseInt(numbers[i]);}return ret;
}function processImgPixelChange(numbers) {var minDiff = Number.MAX_VALUE;var AVERAGE_VALUE = 128 * numbers.length;var finalK = -127;for (var k = -127; k <= 128; k++) {var sum = 0;for (var i = 0; i < numbers.length; i++) {var tmpNumber = numbers[i] + k;if (tmpNumber < 0) {tmpNumber = 0;} else if (tmpNumber > 255) {tmpNumber = 255;}sum += tmpNumber;}var diff = Math.abs(sum - AVERAGE_VALUE);if (diff < minDiff) {minDiff = diff;finalK = k;}}console.log(finalK);
}
(完)