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. linux知识点 ROM,RAM,SRAM,DRAM,Flash

    参考视频:https://www.bilibili.com/video/BV13L4y1b7So?spm_id_from=333.337.search-card.all.click SRAM,DRAM ...

  2. 【Unity3D】Shader Graph简介

    1 Shader Graph 简介 ​ Shader Graph 是 Unity 官方在 2018 年推出的 Shader 制作插件,是图形化的 Shader 制作工具,类似于 Blender 中的 ...

  3. React-Admin后台管理模板|react18+arco+zustand后台解决方案

    基于react18.x+vite4+arco-design自研中后台管理系统解决方案ReactAdmin. react-vite-admin 基于vite4搭建react18.x后台管理项目.使用了r ...

  4. C#计数排序算法

    前言 计数排序是一种非比较性的排序算法,适用于排序一定范围内的整数.它的基本思想是通过统计每个元素的出现次数,然后根据元素的大小依次输出排序结果. 实现原理 首先找出待排序数组中的最大值max和最小值 ...

  5. WebSocket connection to 'ws://127.0.0.1:8089/websocket/0,1,10,admin' failed:

    WebSocket连接失败 背景: 相同项目数据库从mysql变更到sqlite,代码层面基本没有变更,但是WebSocket连接失败,查找多方原因,未找到问题,最后发现新项目JDK为OpenJDK, ...

  6. 开发现代化的.NetCore控制台程序:(3)将nuget包发布到GitHubPackages

    前言 上一篇文章已经把项目模板的nuget包发布到了 nuget 的官方源了,其实还可以发布到其他源,比如 GitHub ,本文记录一下发布到 GitHub Packages 的过程. 注意:本文建立 ...

  7. typeid关键词

    typeid是c++的关键字,typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义) ISO C++标准并没有确切定义type_info,它的确 ...

  8. 【主流技术】详解 Spring Boot 2.7.x 集成 ElasticSearch7.x 全过程(二)

    目录 前言 一.添加依赖 二. yml 配置 三.注入依赖 四.CRUD 常用 API ES 实体类 documents 操作 常见条件查询(重点) 分页查询 排序 构造查询 测试调用 五.文章小结 ...

  9. uni-app学习笔记——路由与页面跳转

    小颖最近在学习小程序,怕自己前看后忘,毕竟还没开始进入项目实践中,就自己瞎倒腾嘻嘻,今天来看下  uni-app  的路由与页面跳转,小颖就简单列举下它们的用法,具体的大家可以看官网哦!啦啦啦啦啦  ...

  10. DES加密技术概述与应用

    一.引言 随着信息技术的飞速发展,数据安全已成为越来越受到重视的问题.数据加密技术作为保障信息安全的核心技术之一,得到了广泛的研究和应用.DES(Data Encryption Standard)作为 ...