2023-09-05:请用go语言编写。一个图像有n个像素点,存储在一个长度为n的数组arr里,

每个像素点的取值范围[0,s]的整数,

请你给图像每个像素点值加上一个整数k(可以是负数),

像素值会自动截取到[0,s]范围,

当像素值<0,会更改为0,当新像素值>s,会更改为s,

这样就可以得到新的arr,想让所有像素点的平均值最接近中位值s/2, 向下取整。

请输出这个整数k, 如有多个整数k都满足, 输出小的那个。

1 <= n <= 10^6,

1 <= s <= 10^18。

来自华为OD。

来自左程云

答案2023-09-05:

根据代码和题目描述,可以将算法分为以下三种不同的方法:

方法一:暴力方法

  • 这种方法通过枚举k的值来计算每个像素值加上k后的平均值,然后选择平均值最接近中位值s/2的k。

  • 该方法采用两层循环:外层循环枚举k的取值,内层循环计算平均值。

  • 时间复杂度:O(n^2)

  • 空间复杂度:O(1)

方法二:优化暴力方法

  • 这种方法在暴力方法的基础上进行了一些优化,采用二分查找来减少计算的次数。

  • 首先,确定k的取值范围为[-s, s],然后进行二分查找来逼近平均值最接近中位值s/2的k。

  • 时间复杂度:O(n*log(s))

  • 空间复杂度:O(1)

方法三:正式方法(最优解)

  • 这种方法是一种最优解,通过先对数组arr进行排序,然后使用前缀和数组pre来存储累加和,以便在计算过程中快速计算区间和。

  • 确定k的取值范围,根据k的正负分别进行二分查找,得到最接近中位值s/2的k。

  • 时间复杂度:O(nlog(n) + log(s)log(n))

  • 空间复杂度:O(n)

go完整代码如下:

package main

import (
"fmt"
"math"
"math/rand"
"sort"
) // 暴力方法
// 为了测试
func best1(arr []int, s int) int {
half := s / 2
average := -100000
ans := -s
for k := -s; k <= s; k++ {
curAverage := average1(arr, k, s)
if math.Abs(float64(half-curAverage)) < math.Abs(float64(half-average)) {
average = curAverage
ans = k
}
}
return ans
} // 暴力方法
// 为了测试
func average1(arr []int, k, s int) int {
sum := 0
for _, num := range arr {
value := num + k
if value < 0 {
sum += 0
} else if value > s {
sum += s
} else {
sum += value
}
}
return sum / len(arr)
} // 优化了一下,但不是最优解
func best2(arr []int, s int) int {
l := -s
r := s
m := 0
half := s / 2
average := -s
ans := 0
for l <= r {
m = (l + r) / 2
curAverage := average1(arr, m, s)
if math.Abs(float64(half-curAverage)) < math.Abs(float64(half-average)) ||
(math.Abs(float64(half-curAverage)) == math.Abs(float64(half-average)) && m < ans) {
average = curAverage
ans = m
}
if curAverage >= half {
r = m - 1
} else {
l = m + 1
}
}
return ans
} // 正式方法
// 最优解
// O(N * logN) + O(logS * logN)
func best3(arr []int, s int) int {
sort.Ints(arr)
sum := make([]int, len(arr))
sum[0] = arr[0]
for i := 1; i < len(arr); i++ {
sum[i] = sum[i-1] + arr[i]
}
l := -s
r := s
m := 0
half := s / 2
average := -s
ans := 0
for l <= r {
m = (l + r) / 2
curAverage := average3(arr, sum, m, s)
if math.Abs(float64(half-curAverage)) < math.Abs(float64(half-average)) ||
(math.Abs(float64(half-curAverage)) == math.Abs(float64(half-average)) && m < ans) {
average = curAverage
ans = m
}
if curAverage >= half {
r = m - 1
} else {
l = m + 1
}
}
return ans
} func average3(arr []int, pre []int, k, s int) int {
n := len(arr)
if k < 0 {
l := bsZero(arr, k)
sum := rangeSum(pre, l+1, n-1)
return (sum + (k * (n - l - 1))) / n
} else {
r := bsS(arr, k, s)
sum := rangeSum(pre, 0, r-1)
return (sum + (k * r) + (s * (n - r))) / n
}
} func bsZero(arr []int, k int) int {
ans := -1
l := 0
r := len(arr) - 1
var m int
for l <= r {
m = (l + r) / 2
if arr[m]+k <= 0 {
ans = m
l = m + 1
} else {
r = m - 1
}
}
return ans
} func bsS(arr []int, k, s int) int {
ans := len(arr)
l := 0
r := len(arr) - 1
var m int
for l <= r {
m = (l + r) / 2
if arr[m]+k >= s {
ans = m
r = m - 1
} else {
l = m + 1
}
}
return ans
} func rangeSum(pre []int, l, r int) int {
if l > r {
return 0
}
if l == 0 {
return pre[r]
}
return pre[r] - pre[l-1]
} // 为了测试
func randomArray(n, s int) []int {
arr := make([]int, n)
for i := 0; i < n; i++ {
arr[i] = randInt(0, s)
}
return arr
} func randInt(min, max int) int {
return min + rand.Intn(max-min+1)
} func main() {
N := 50
S := 500
testTimes := 10000
fmt.Println("测试开始")
for i := 0; i < testTimes; i++ {
n := randInt(1, N)
s := randInt(1, S)
arr := randomArray(n, s)
ans1 := best1(arr, s)
ans2 := best2(arr, s)
ans3 := best3(arr, s)
if ans1 != ans2 || ans1 != ans3 {
fmt.Println("出错了!")
}
}
fmt.Println("测试结束")
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <algorithm> using namespace std; int average1(vector<int>& arr, int k, int s);
int average3(vector<int>& arr, vector<int>& pre, int k, int s);
int bsZero(vector<int>& arr, int k);
int bsS(vector<int>& arr, int k, int s);
int rangeSum(vector<int>& pre, int l, int r);
int best1(vector<int>& arr, int s);
int best2(vector<int>& arr, int s);
int best3(vector<int>& arr, int s);
vector<int> randomArray(int n, int s);
void test(); int average1(vector<int>& arr, int k, int s) {
int sum = 0;
for (int num : arr) {
int value = num + k;
if (value < 0) {
sum += 0;
}
else if (value > s) {
sum += s;
}
else {
sum += value;
}
}
return sum / arr.size();
} int average3(vector<int>& arr, vector<int>& pre, int k, int s) {
int n = arr.size();
if (k < 0) {
int l = bsZero(arr, k);
int sum = rangeSum(pre, l + 1, n - 1);
return (sum + (k * (n - l - 1))) / n;
}
else {
int r = bsS(arr, k, s);
int sum = rangeSum(pre, 0, r - 1);
return (sum + (k * r) + (s * (n - r))) / n;
}
} int bsZero(vector<int>& arr, int k) {
int ans = -1;
int l = 0;
int r = arr.size() - 1;
int m;
while (l <= r) {
m = (l + r) / 2;
if (arr[m] + k <= 0) {
ans = m;
l = m + 1;
}
else {
r = m - 1;
}
}
return ans;
} int bsS(vector<int>& arr, int k, int s) {
int ans = arr.size();
int l = 0;
int r = arr.size() - 1;
int m;
while (l <= r) {
m = (l + r) / 2;
if (arr[m] + k >= s) {
ans = m;
r = m - 1;
}
else {
l = m + 1;
}
}
return ans;
} int rangeSum(vector<int>& pre, int l, int r) {
if (l > r) {
return 0;
}
return l == 0 ? pre[r] : (pre[r] - pre[l - 1]);
} int best1(vector<int>& arr, int s) {
int half = s / 2;
int average = -100000;
int ans = -s;
for (int k = -s; k <= s; k++) {
int curAverage = average1(arr, k, s);
if (abs(half - curAverage) < abs(half - average)) {
average = curAverage;
ans = k;
}
}
return ans;
} int best2(vector<int>& arr, int s) {
int l = -s;
int r = s;
int m = 0;
int half = s / 2;
int average = -s;
int ans = 0;
while (l <= r) {
m = (l + r) / 2;
int curAverage = average1(arr, m, s);
if ((abs(half - curAverage) < abs(half - average))
|| ((abs(half - curAverage) == abs(half - average)) && m < ans)) {
average = curAverage;
ans = m;
}
if (curAverage >= half) {
r = m - 1;
}
else {
l = m + 1;
}
}
return ans;
} int best3(vector<int>& arr, int s) {
sort(arr.begin(), arr.end());
vector<int> sum(arr.size());
sum[0] = arr[0];
for (int i = 1; i < arr.size(); i++) {
sum[i] = sum[i - 1] + arr[i];
}
int l = -s;
int r = s;
int m = 0;
int half = s / 2;
int average = -s;
int ans = 0;
while (l <= r) {
m = (l + r) / 2;
int curAverage = average3(arr, sum, m, s);
if ((abs(half - curAverage) < abs(half - average))
|| ((abs(half - curAverage) == abs(half - average)) && m < ans)) {
average = curAverage;
ans = m;
}
if (curAverage >= half) {
r = m - 1;
}
else {
l = m + 1;
}
}
return ans;
} vector<int> randomArray(int n, int s) {
vector<int> arr(n);
for (int i = 0; i < n; i++) {
arr[i] = rand() % (s + 1);
}
return arr;
} void test() {
int N = 50;
int S = 500;
int testTimes = 10000;
cout << "测试开始" << endl;
for (int i = 0; i < testTimes; i++) {
int n = rand() % N + 1;
int s = rand() % S + 1;
vector<int> arr = randomArray(n, s);
int ans1 = best1(arr, s);
int ans2 = best2(arr, s);
int ans3 = best3(arr, s);
if (ans1 != ans2 || ans1 != ans3) {
cout << "出错了!" << endl;
}
}
cout << "测试结束" << endl;
} int main() {
test();
return 0;
}

2023-09-05:请用go语言编写。一个图像有n个像素点,存储在一个长度为n的数组arr里, 每个像素点的取值范围[0,s]的整数, 请你给图像每个像素点值加上一个整数k(可以是负数), 像素值会的更多相关文章

  1. 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字

    题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...

  2. 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3

    // test14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...

  3. opencv入门系列教学(五)图像的基本操作(像素值、属性、ROI和边框)

    0.序言 每个图像是由一个个点组成的,而这些点可以表示为像素值的形式. 这篇博客里我们将学会: 访问像素值并修改它们 . 访问图像属性 . 设置感兴趣区域(ROI) . 分割和合并图像. 对于图像的基 ...

  4. 问题-MyBatis不识别Integer值为0的数据

    问题-MyBatis不识别Integer值为0的数据 问题:使用MyBatis的过程中,发现一个值为0的数据,Mybatis所识别,最后定位才发现,是自己的写法有问题, <if test=&qu ...

  5. AE IRasterCursor 改变栅格图层像素值

    1 public void ChangePixelValue(double xMax, double xMin, double yMax, double yMin,double[,] PixelCha ...

  6. C/C++编程笔记:C语言入门知识点(三),请收藏C语言最全笔记!

    今天我们继续来学习C语言的入门知识点,第一课:C/C++编程笔记:C语言入门知识点(二),请收藏C语言最全笔记! 21. 输入 & 输出 当我们提到输入时,这意味着要向程序填充一些数据.输入可 ...

  7. C/C++编程笔记:C语言入门知识点(二),请收藏C语言最全笔记!

    今天我们继续来学习C语言的入门知识点 11. 作用域规则 任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量: 在函数或块内部的局部变量 ...

  8. 请为CMyString类型编写构造函数、copy构造函数、析构函数和赋值运算符函数。

    如下为类型CMyString的声明,请为该类型编写构造函数.copy构造函数.析构函数和赋值运算符函数. class CMyString { public: CMyString(const char* ...

  9. C/C++编程笔记:C语言入门知识点(一),请收藏C语言最全笔记!

    C语言简介 C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的.C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现. 原文链接: ...

  10. (面试题)请用C语言实现在32位环境下,两个无符号长整数相加的函数,相加之和不能存储在64位变量中

    分析:长整数相加,将结果分为高位和低位部分,分别保存在两个32整数中. 比如:unsigned int a = 0xFFFFFFFF, unsigned int b = 0x1, 结果用unsigne ...

随机推荐

  1. Ubuntu更新软件的命令

    更新软件源 apt-get update 更新升级所有软件 apt-get upgrade 更新某个软件 apt-get upgrade 名 列出可更新的软件 apt list --upgradabl ...

  2. LVS+keepalived配置高可用架构和负载均衡机制(1)

    一.基础知识 1. 四层负载均衡(基于IP+端口的负载均衡) 所谓四层负载均衡,也就是主要通过报文中的目标ip地址和端口,再加上负载均衡设备设置的服务器选择方式(分发策略,轮询),决定最终选择的内部服 ...

  3. Java21上手体验-分代ZGC和虚拟线程

    一.导语 几天前Oracle刚刚发布了Java21, 由于这是最新的LTS版本,引起了大家的关注. 我也第一时间在个人项目中进行了升级体验. 一探究竟,和大家分享. 二.Java21更新内容介绍 官方 ...

  4. Qt信号槽与事件循环学习笔记

    事件与事件循环 信号槽机制 事件与事件循环 在Qt中,事件(event)被封装为QEvent类/子类对象,用来表示应用内部或外部发生的各种事情.事件可以被任何QObject子类的对象接收并处理. 根据 ...

  5. Chromium Command Buffer原理解析

    Command Buffer 是支撑 Chromium 多进程硬件加速渲染的核心技术之一.它基于 OpenGLES2.0 定义了一套序列化协议,这套协议规定了所有 OpenGLES2.0 命令的序列化 ...

  6. HTML DOM 之一:访问、修改、删除HTML内容

    什么是 DOM? DOM 是 W3C(万维网联盟)的标准. DOM 定义了访问 HTML 和 XML 文档的标准: "W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和 ...

  7. 2023 PolarD&N靶场通关笔记 Crypto

    简单类: keyboard2.0 21 31 41 53 63 73 62 72 82 81 91 01 51 61 71 提示:解出来的内容转换为md5值后加上flag{} 数字被分成五组,每组包含 ...

  8. Senparc 基础库全面适配 .NET 8.0

    概要 Senparc 全家桶中的基础库已经全面适配 .NET 8.0,目前随着 .NET 8.0 的 RC 版本不断发布,对应的版本号也将同步进行更新,直到本月 Ignite 大会微软官方发布 .NE ...

  9. 2022.7.15 jiazhaopeng 讲课纪要

    前言 由于难度仍然过高,难度再次下调,这节课主要在水绿.这节课讲的是并查集,之所以是以绿题为主是因为上了绿之后的题有一大半都要结合别的东西,初中生不会,所以只能讲的简单一点. ORZ%%% jzp学长 ...

  10. (Good topic)卡牌分组(3.27leetcode每日打卡)

    给定一副牌,每张牌上都写着一个整数. 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:  每组都有 X 张牌. 组内所有的牌上都写着相同的整数. 仅当你可选的 X &g ...