• 华为OD机考算法题:简单的自动曝光


    题目部分

    题目简单的自动曝光
    难度
    题目说明一个图像有 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 次。

    此算法的时间复杂度为 O(n),空间复杂度为 O(1)。


    代码实现

    Java代码

    1. import java.util.Scanner;
    2. /**
    3. * 简单的自动曝光
    4. * @since 2023.09.09
    5. * @version 0.1
    6. * @author Frank
    7. *
    8. */
    9. public class ImgPixelChange {
    10. public static void main(String[] args) {
    11. Scanner sc = new Scanner(System.in);
    12. while (sc.hasNext()) {
    13. String input = sc.nextLine();
    14. String[] strNumbers = input.split( " " );
    15. int[] numbers = convertStrNumbers2Int( strNumbers);
    16. processImgPixelChange( numbers );
    17. }
    18. }
    19. private static int[] convertStrNumbers2Int( String[] numbers)
    20. {
    21. int[] ret = new int[numbers.length];
    22. for( int i = 0; i < numbers.length; i ++ )
    23. {
    24. ret[i] = Integer.parseInt( numbers[i] );
    25. }
    26. return ret;
    27. }
    28. private static void processImgPixelChange( int numbers[] )
    29. {
    30. int minDiff = Integer.MAX_VALUE;
    31. int AVERAGE_VALUE = 128 * numbers.length;
    32. int finalK = -127;
    33. for( int k = -127; k <= 128; k ++ )
    34. {
    35. int sum = 0;
    36. for( int i = 0; i < numbers.length; i ++ )
    37. {
    38. int tmpNumber = numbers[i] + k;
    39. if( tmpNumber < 0 )
    40. {
    41. tmpNumber = 0;
    42. }else if( tmpNumber > 255 )
    43. {
    44. tmpNumber = 255;
    45. }
    46. sum += tmpNumber;
    47. }
    48. int diff = Math.abs( sum - AVERAGE_VALUE );
    49. if( diff < minDiff )
    50. {
    51. minDiff = diff;
    52. finalK = k;
    53. }
    54. }
    55. System.out.println( finalK );
    56. }
    57. }

    JavaScript代码

    1. const rl = require("readline").createInterface({ input: process.stdin });
    2. var iter = rl[Symbol.asyncIterator]();
    3. const readline = async () => (await iter.next()).value;
    4. void async function() {
    5. while (line = await readline()) {
    6. var strNumbers = line.split(" ");
    7. var numbers = convertStrNumbers2Int(strNumbers);
    8. processImgPixelChange(numbers);
    9. }
    10. }();
    11. function convertStrNumbers2Int( numbers) {
    12. var ret = new Array(numbers.length );
    13. for ( var i = 0; i < numbers.length; i++) {
    14. ret[i] = parseInt(numbers[i]);
    15. }
    16. return ret;
    17. }
    18. function processImgPixelChange(numbers) {
    19. var minDiff = Number.MAX_VALUE;
    20. var AVERAGE_VALUE = 128 * numbers.length;
    21. var finalK = -127;
    22. for (var k = -127; k <= 128; k++) {
    23. var sum = 0;
    24. for (var i = 0; i < numbers.length; i++) {
    25. var tmpNumber = numbers[i] + k;
    26. if (tmpNumber < 0) {
    27. tmpNumber = 0;
    28. } else if (tmpNumber > 255) {
    29. tmpNumber = 255;
    30. }
    31. sum += tmpNumber;
    32. }
    33. var diff = Math.abs(sum - AVERAGE_VALUE);
    34. if (diff < minDiff) {
    35. minDiff = diff;
    36. finalK = k;
    37. }
    38. }
    39. console.log(finalK);
    40. }

    (完)

  • 相关阅读:
    疫情后的旅游业:恢复和变革
    jQuery表单校验jquery.validate.js的使用
    基于JavaSwing开发选课系统的设计与实现 课程设计 大作业 毕业设计
    Nuxt.js 中定制 error.vue 错误缺省页
    brew 下载 nvm 之后,nvm command not found
    PMP考试可以延缓考吗?解答来了!
    2022年数据泄露平均成本高达435万美元,创历史新高!
    flutter环境之安装FVM
    C++学习day7
    [OpenJDK:环境变量配置]:填充Profile并修改默认配置
  • 原文地址:https://blog.csdn.net/ZiJinShi/article/details/132767997