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. 使用Arduino制作摩尔斯电码收发器

    摩尔斯电码通过不同的排列顺序来表达不同的英文字母.数字和标点符号等.在今天,国际摩尔斯电码依然被使用着.比如,摩尔斯电码最广为人知的用法发送求救信号SOS,SOS信号的组合方式为:.再比如,假设我们通 ...

  2. Gossip in Hyperledger Fabric

    1. Gossip协议基础 1.1 什么是分布式系统 分布式系统(Distributed System)是由多台计算机或计算节点组成的计算机系统,这些计算节点通过网络连接在一起,并协同工作以完成共同的 ...

  3. Kraft模式下Kafka脚本的使用

    Kafka集群 版本:V3.5.1 名称 Node1 Node2 Node3 IP 172.29.145.157 172.29.145.182 172.29.145.183 (1)查看Kraft集群中 ...

  4. mapState、mapGetters、mapMutations、mapActions学习

    https://next.vuex.vuejs.org/zh/guide/state.html#mapstate-%E8%BE%85%E5%8A%A9%E5%87%BD%E6%95%B0 https: ...

  5. Backgrounds

    有人私信要背景图,所以一起放出来了qwq 感觉这个博皮的动效选深色并且带点漂浮感的背景会比较好看(? 选图基本按这个标准选的,实际上比较亮的几张图已经被我手动拉低亮度了.(不过还是不太行/kk 备注里 ...

  6. JavaScript用策略模式消除if else 和 switch

    js程序中最常用的if else循环,如果分枝很多的的情况下难免使写出的程序又臭又长,但是根据需求又必须将这些分支处理,此时稍有经验的程序员可能会想到用switch case优化但是只是仅仅做到利于阅 ...

  7. SpringBoot系列之MyBatis Plus自动填充实现

    系列博客专栏:SpringBoot2.0系列博客专栏 开发环境 JDK 1.8 SpringBoot2.2.1 Maven 3.2+ Mysql5.7.36 开发工具 IntelliJ IDEA sm ...

  8. 从BST到LSM的进阶之路

    前言 相信大家之前都了解过很多种数据结构,我之前总是两两的,也就是从局部上去进行比较,没有从整体上进行这些树的发展脉络进行梳理,因此经常看完没多久就忘了.看来确实是需要从本源出发,不仅要知其然还要知其 ...

  9. React、Umi、RN 整体理解

    可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么? React 1. React 起源和发展(是什么?) React 是用于构建用户界面的 Jav ...

  10. Windows文件句柄无效

    今天我用FreeFileSync从移动硬盘复制一个名为Con的文件夹到本地硬盘,复制失败. 通过文件夹资源管理器Explorer直接访问文件夹则提示"禁止访问",右键属性切换到安全 ...