2023-08-30:用go语言编写。两个魔法卷轴问题。 给定一个数组arr,其中可能有正、负、0, 一个魔法卷轴可以把arr中连续的一段全变成0,你希望数组整体的累加和尽可能大。 你有两个魔法卷轴,
2023-08-30:用go语言编写。两个魔法卷轴问题。
给定一个数组arr,其中可能有正、负、0,
一个魔法卷轴可以把arr中连续的一段全变成0,你希望数组整体的累加和尽可能大。
你有两个魔法卷轴,请返回数组尽可能大的累加和。
1 <= arr长度 <= 100000,
-100000 <= arr里的值 <= 100000。
来自微众银行。
来自左程云。
答案2023-08-30:
算法maxSum1:
1.定义一个辅助函数max,用于返回两个数中的最大值。
2.定义函数maxSum1,接收一个整数数组arr作为参数,返回一个整数。
3.初始化变量p1为0,遍历数组arr,累加每个元素到p1。
4.获取数组arr的长度n。
5.调用函数mustOneScroll(arr, 0, n-1),返回一个整数,并赋值给变量p2。
6.初始化变量p3为math.MinInt32。
7.循环变量i从1到n-1:
调用函数mustOneScroll(arr, 0, i-1),返回一个整数,并与调用函数mustOneScroll(arr, i, n-1)的返回值相加,得到一个新的整数。
调用max函数,将p3与新整数比较,取较大值赋给p3。
8.调用max函数三次,分别比较p1、p2和p3的值,返回最大值作为结果。
算法maxSum2:
1.定义一个辅助函数max,用于返回两个数中的最大值。
2.定义函数maxSum2,接收一个整数数组arr作为参数,返回一个整数。
3.如果数组arr的长度为0,直接返回0。
4.初始化变量p1为0,遍历数组arr,累加每个元素到p1。
5.获取数组arr的长度n。
6.创建长度为n的数组left,用于存储每个位置左边范围内的最大累加和。
7.初始化变量sum为arr[0],maxSum为max(0, sum)。
8.循环变量i从1到n-1:
将left[i]设置为max(left[i-1]+arr[i], maxSum)。
累加arr[i]到sum。
用max函数比较maxSum和sum的值,将较大值赋给maxSum。
9.创建长度为n的数组right,用于存储每个位置右边范围内的最大累加和。
10.初始化变量sum为arr[n-1],maxSum为max(0, sum)。
11.倒序循环变量i从n-2到0:
- 将right[i]设置为max(arr[i]+right[i+1], maxSum)。
- 累加arr[i]到sum。
- 用max函数比较maxSum和sum的值,将较大值赋给maxSum。
12.初始化变量p2为left[n-1]。
13.初始化变量p3为math.MinInt32。
14.循环变量i从1到n-1:
- 将left[i-1]+right[i]的值与p3比较,取较大值赋给p3。
15.调用max函数三次,分别比较p1、p2和p3的值,返回最大值作为结果。
时间复杂度和空间复杂度:
对于maxSum1算法,时间复杂度为O(N^3),其中N为数组arr的长度。空间复杂度为O(1)。
对于maxSum2算法,时间复杂度为O(N),其中N为数组arr的长度。空间复杂度为O(N)(需要额外的left和right数组)。
go完整代码如下:
package main
import (
"fmt"
"math"
"math/rand"
"time"
)
// 暴力方法
// 为了测试
func maxSum1(arr []int) int {
p1 := 0
for _, num := range arr {
p1 += num
}
n := len(arr)
p2 := mustOneScroll(arr, 0, n-1)
p3 := math.MinInt32
for i := 1; i < n; i++ {
p3 = max(p3, mustOneScroll(arr, 0, i-1)+mustOneScroll(arr, i, n-1))
}
return max(p1, max(p2, p3))
}
// 为了测试
func mustOneScroll(arr []int, L, R int) int {
ans := math.MinInt32
for a := L; a <= R; a++ {
for b := a; b <= R; b++ {
curAns := 0
for i := L; i < a; i++ {
curAns += arr[i]
}
for i := b + 1; i <= R; i++ {
curAns += arr[i]
}
ans = max(ans, curAns)
}
}
return ans
}
// 正式方法
// 时间复杂度O(N)
func maxSum2(arr []int) int {
if len(arr) == 0 {
return 0
}
// 一个卷轴也不用
p1 := 0
for _, num := range arr {
p1 += num
}
n := len(arr)
// left[i] : 0 ~ i范围上,一定要用一次卷轴的情况下,最大累加和多少
left := make([]int, n)
// left[0] = 0 : 0 ~ 0,一定要用一次卷轴的情况下,最大累加和多少
// 每一步的前缀和
// 0~0 前缀和
sum := arr[0]
// 之前所有前缀和的,最大值
maxSum := max(0, sum)
for i := 1; i < n; i++ {
// left[i - 1] + arr[i]
// maxSum : 之前所有前缀和的,最大值
left[i] = max(left[i-1]+arr[i], maxSum)
sum += arr[i]
maxSum = max(maxSum, sum)
}
// 只用一次卷轴,必须用,0~n-1范围上的解,第二种可能性
p2 := left[n-1]
// 第三种 :一定要用两次卷轴
right := make([]int, n)
// right[i] : i ~ n-1范围上,一定要用一次卷轴的情况下,最大累加和多少
sum = arr[n-1]
maxSum = max(0, sum)
for i := n - 2; i >= 0; i-- {
right[i] = max(arr[i]+right[i+1], maxSum)
sum += arr[i]
maxSum = max(maxSum, sum)
}
p3 := math.MinInt32
for i := 1; i < n; i++ {
// 0..0 1...n-1
// 0..1 2...n-1
// 0..2 3...n-1
p3 = max(p3, left[i-1]+right[i])
}
return max(p1, max(p2, p3))
}
// 辅助函数,返回两个数中的最大值
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 为了测试
func randomArray(n, v int) []int {
arr := make([]int, n)
rand.Seed(time.Now().UnixNano())
for i := 0; i < n; i++ {
arr[i] = rand.Intn(2*v+1) - v
}
return arr
}
func main() {
rand.Seed(time.Now().UnixMilli())
N := 50
V := 100
testTimes := 10000
fmt.Println("测试开始")
for i := 0; i < testTimes; i++ {
n := rand.Intn(N)
arr := randomArray(n, V)
ans1 := maxSum1(arr)
ans2 := maxSum2(arr)
if ans1 != ans2 {
fmt.Println("出错了!")
}
}
fmt.Println("测试结束")
}
rust完整代码如下:
use std::cmp;
// 暴力方法
// 为了测试
fn max_sum1(arr: &[i32]) -> i32 {
let mut p1 = 0;
for &num in arr {
p1 += num;
}
let n = arr.len() as i32;
let mut p2 = must_one_scroll(arr, 0, n - 1);
let mut p3 = i32::MIN;
for i in 1..n {
p3 = cmp::max(
p3,
must_one_scroll(arr, 0, i - 1) + must_one_scroll(arr, i, n - 1),
);
}
cmp::max(p1, cmp::max(p2, p3))
}
// 为了测试
fn must_one_scroll(arr: &[i32], l: i32, r: i32) -> i32 {
let mut ans = i32::MIN;
for a in l..=r {
for b in a..=r {
let mut cur_ans = 0;
for i in l..a {
cur_ans += arr[i as usize];
}
for i in b + 1..=r {
cur_ans += arr[i as usize];
}
ans = cmp::max(ans, cur_ans);
}
}
ans
}
// 正式方法
// 时间复杂度O(N)
fn max_sum2(arr: &[i32]) -> i32 {
if arr.is_empty() {
return 0;
}
// 一个卷轴也不用
let mut p1 = 0;
for &num in arr {
p1 += num;
}
let n = arr.len() as i32;
// left[i] : 0 ~ i范围上,一定要用一次卷轴的情况下,最大累加和多少
let mut left = vec![0; n as usize];
// left[0] = 0 : 0 ~ 0,一定要用一次卷轴的情况下,最大累加和多少
// 每一步的前缀和
// 0~0 前缀和
let mut sum = arr[0];
// 之前所有前缀和的,最大值
let mut max_sum = cmp::max(0, sum);
for i in 1..n {
// left[i - 1] + arr[i]
// max_sum : 之前所有前缀和的,最大值
left[i as usize] = cmp::max(left[i as usize - 1] + arr[i as usize], max_sum);
sum += arr[i as usize];
max_sum = cmp::max(max_sum, sum);
}
// 只用一次卷轴,必须用,0~n-1范围上的解,第二种可能性
let p2 = left[n as usize - 1];
// 第三种 :一定要用两次卷轴
let mut right = vec![0; n as usize];
// right[i] : i ~ n-1范围上,一定要用一次卷轴的情况下,最大累加和多少
sum = arr[n as usize - 1];
max_sum = cmp::max(0, sum);
for i in (0..n - 1).rev() {
right[i as usize] = cmp::max(arr[i as usize] + right[i as usize + 1], max_sum);
sum += arr[i as usize];
max_sum = cmp::max(max_sum, sum);
}
let mut p3 = i32::MIN;
for i in 1..n {
// 0..0 1...n-1
// 0..1 2...n-1
// 0..2 3...n-1
p3 = cmp::max(p3, left[i as usize - 1] + right[i as usize]);
}
cmp::max(p1, cmp::max(p2, p3))
}
// 为了测试
fn random_array(n: usize, v: i32) -> Vec<i32> {
let mut arr = vec![0; n];
for i in 0..n {
arr[i] = (rand::random::<i32>() % (v * 2 + 1)) - v;
}
arr
}
// 为了测试
fn main() {
let n = 50;
let v = 100;
let test_times = 10_000;
println!("测试开始");
for _ in 0..test_times {
let n = rand::random::<usize>() % n;
let arr = random_array(n, v);
let ans1 = max_sum1(&arr);
let ans2 = max_sum2(&arr);
if ans1 != ans2 {
println!("出错了!");
}
}
println!("测试结束");
}
c++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int mustOneScroll(vector<int>& arr, int L, int R) {
int ans = INT_MIN;
for (int a = L; a <= R; a++) {
for (int b = a; b <= R; b++) {
int curAns = 0;
for (int i = L; i < a; i++) {
curAns += arr[i];
}
for (int i = b + 1; i <= R; i++) {
curAns += arr[i];
}
ans = max(ans, curAns);
}
}
return ans;
}
int maxSum1(vector<int>& arr) {
int p1 = 0;
for (int num : arr) {
p1 += num;
}
int n = arr.size();
int p2 = mustOneScroll(arr, 0, n - 1);
int p3 = INT_MIN;
for (int i = 1; i < n; i++) {
p3 = max(p3, mustOneScroll(arr, 0, i - 1) + mustOneScroll(arr, i, n - 1));
}
return max(p1, max(p2, p3));
}
int maxSum2(vector<int>& arr) {
if (arr.size() == 0) {
return 0;
}
int p1 = 0;
for (int num : arr) {
p1 += num;
}
int n = arr.size();
vector<int> left(n);
int sum = arr[0];
int maxSum = max(0, sum);
for (int i = 1; i < n; i++) {
left[i] = max(left[i - 1] + arr[i], maxSum);
sum += arr[i];
maxSum = max(maxSum, sum);
}
int p2 = left[n - 1];
vector<int> right(n);
sum = arr[n - 1];
maxSum = max(0, sum);
for (int i = n - 2; i >= 0; i--) {
right[i] = max(arr[i] + right[i + 1], maxSum);
sum += arr[i];
maxSum = max(maxSum, sum);
}
int p3 = INT_MIN;
for (int i = 1; i < n; i++) {
p3 = max(p3, left[i - 1] + right[i]);
}
return max(p1, max(p2, p3));
}
vector<int> randomArray(int n, int v) {
vector<int> arr(n);
for (int i = 0; i < n; i++) {
arr[i] = rand() % (2 * v + 1) - v;
}
return arr;
}
int main() {
int N = 50;
int V = 100;
int testTimes = 10000;
cout << "测试开始" << endl;
for (int i = 0; i < testTimes; i++) {
int n = rand() % N;
vector<int> arr = randomArray(n, V);
int ans1 = maxSum1(arr);
int ans2 = maxSum2(arr);
if (ans1 != ans2) {
cout << "出错了!" << endl;
}
}
cout << "测试结束" << endl;
return 0;
}
c完整代码如下:
#include <stdio.h>
#include <stdlib.h>
int maxSum1(int* arr, int n);
int mustOneScroll(int* arr, int L, int R);
int maxSum2(int* arr, int n);
int* randomArray(int n, int v);
int maxSum1(int* arr, int n) {
int p1 = 0;
int* ptr = arr;
for (int i = 0; i < n; i++) {
p1 += *ptr++;
}
int p2 = mustOneScroll(arr, 0, n - 1);
int p3 = -INT_MAX;
for (int i = 1; i < n; i++) {
p3 = (p3 > mustOneScroll(arr, 0, i - 1) + mustOneScroll(arr, i, n - 1)) ? p3 : mustOneScroll(arr, 0, i - 1) + mustOneScroll(arr, i, n - 1);
}
return (p1 > (p2 > p3 ? p2 : p3)) ? p1 : ((p2 > p3) ? p2 : p3);
}
int mustOneScroll(int* arr, int L, int R) {
int ans = -INT_MAX;
for (int a = L; a <= R; a++) {
for (int b = a; b <= R; b++) {
int curAns = 0;
for (int i = L; i < a; i++) {
curAns += *(arr + i);
}
for (int i = b + 1; i <= R; i++) {
curAns += *(arr + i);
}
ans = (ans > curAns) ? ans : curAns;
}
}
return ans;
}
int maxSum2(int* arr, int n) {
if (n == 0) {
return 0;
}
int p1 = 0;
int* ptr = arr;
for (int i = 0; i < n; i++) {
p1 += *ptr++;
}
int* left = (int*)malloc(n * sizeof(int));
int* right = (int*)malloc(n * sizeof(int));
int sum, maxSum;
sum = *arr;
maxSum = (0 > sum) ? 0 : sum;
*left = (0 > (*arr)) ? 0 : (*arr);
for (int i = 1; i < n; i++) {
*(left + i) = (*(left + i - 1) + *(arr + i) > maxSum) ? *(left + i - 1) + *(arr + i) : maxSum;
sum += *(arr + i);
maxSum = (maxSum > sum) ? maxSum : sum;
}
int p2 = *(left + (n - 1));
sum = *(arr + (n - 1));
maxSum = (0 > sum) ? 0 : sum;
*(right + (n - 1)) = (0 > (*(arr + (n - 1)))) ? 0 : (*(arr + (n - 1)));
for (int i = n - 2; i >= 0; i--) {
*(right + i) = (*(arr + i) + *(right + i + 1) > maxSum) ? (*(arr + i) + *(right + i + 1)) : maxSum;
sum += *(arr + i);
maxSum = (maxSum > sum) ? maxSum : sum;
}
int p3 = -INT_MAX;
for (int i = 1; i < n; i++) {
p3 = (p3 > (*(left + i - 1) + *(right + i))) ? p3 : (*(left + i - 1) + *(right + i));
}
int result = (p1 > (p2 > p3 ? p2 : p3)) ? p1 : ((p2 > p3) ? p2 : p3);
free(left);
free(right);
return result;
}
int* randomArray(int n, int v) {
int* arr = (int*)malloc(n * sizeof(int));
int* ptr = arr;
for (int i = 0; i < n; i++) {
*ptr++ = (rand() % (2 * v + 1)) - v;
}
return arr;
}
int main() {
int N = 50;
int V = 100;
int testTimes = 10000;
printf("测试开始\n");
for (int i = 0; i < testTimes; i++) {
int n = rand() % N;
int* arr = randomArray(n, V);
int ans1 = maxSum1(arr, n);
int ans2 = maxSum2(arr, n);
if (ans1 != ans2) {
printf("出错了!\n");
}
free(arr);
}
printf("测试结束\n");
return 0;
}
2023-08-30:用go语言编写。两个魔法卷轴问题。 给定一个数组arr,其中可能有正、负、0, 一个魔法卷轴可以把arr中连续的一段全变成0,你希望数组整体的累加和尽可能大。 你有两个魔法卷轴,的更多相关文章
- VS2008 格式化时候乱码 或者 为全为0
前几天一直发现写入文件的数据全是0 ,找了非常长时间发现问题在以下的地方: P:a是一个float数,如31.000000,然后运行以下的格式化语句时,结果str的值全是0. (我知道讲float格式 ...
- 使用OC语言编写两个超大数相乘或相加的算法的思路和超大正整数相乘的代码
正文: 在编程中,无论是OC还是C亦或是C++语言,所声明的整数变量都会在内存中占有固定的存储空间,而这些存储空间都是固定的. 比如我们知道的int.long.short.unsigend int.u ...
- CF E. Vasya and a Tree】 dfs+树状数组(给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值)
题意: 给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值 ...
- 偶然在博客中见对百度一个面试题的探讨,写些自己的看法以及指出探讨中不对的观点:百度面试题:求绝对值最小的数 有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现 例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。
今天申请了博客园账号,在下班后阅览博客时发现了一个关于百度面试题探讨的博客(其实是个很基础的问题),此博客url为:http://www.blogjava.net/nokiaguy/archive/2 ...
- 使用Go语言编写区块链P2P网络(译)(转)
转自:https://mp.weixin.qq.com/s/2daFH9Ej5fVlWmpsN5HZzw 外文链接: https://medium.com/coinmonks/code-a-simpl ...
- Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架
转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏 ...
- 用 C 语言编写一个简单的垃圾回收器
人们似乎觉得编写垃圾回收机制是非常难的,是一种仅仅有少数智者和Hans Boehm(et al)才干理解的高深魔法.我觉得编写垃圾回收最难的地方就是内存分配,这和阅读K&R所写的malloc例 ...
- linux c语言编写一个shell壳
目的:我们要用c语言编写一个shell可以运行在linux机器上的. 介绍:shell所在的层次 我们要做的是操作系统,用于用户与操作系统进行交互的myhsell 思路:用户输入 一行字符串,我们先 ...
- 近50种语言编写的“Hello, World”,你会几种?可不要贪杯哦~
本文转自公众号CSDN(ID:CSDNnews)作者:Sylvain Saurel,译者:风车云马
- 用Java语言编写一个简易画板
讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目 ...
随机推荐
- Linux 创建 Python 虚拟环境
Linux 创建 Python 虚拟环境 0. 前言 网上教程太杂太乱,要么排版不好看,要么讲半天讲不到重点,故做此篇,精简干练. 1. 安装virtualenv 先用pip安装virtualenv第 ...
- Random库用法详解
梅森旋转算法实现 基本随机数函数 seed(a=None): 初始化给定的随机数种子,默认为当前系统时间. 只要随机数种子相同,产生的随机数序列也相同. random(): 生成一个[0.0,1.0] ...
- 从0搭建Vue3组件库(十三):引入Husky规范git提交
为什么要引入 husky? 虽然我们项目中引入了prettier和eslint对代码格式进行了校验,但是多人开发的时候难免依然会有人提交不符合规范的代码到仓库中,如果我们拉取到这种代码还得慢慢对其进行 ...
- 沉思篇-剖析Jetpack的ViewModel
ViewModel做为架构组件的三元老之一,是实现MVVM的有力武器. ViewModel的设计目标 ViewModel的基本功能就是管理UI的数据.其实,从职责上来说,这又是对Activity和Fr ...
- 前端Vue自定义服务说明弹窗弹框 自下而上底部弹框
前端Vue自定义服务说明弹窗弹框 自下而上底部弹框, 请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13108 效果图如下: cc-serv ...
- Dapr 发布模糊测试报告|Dapr 完成模糊测试审核
Dapr 团队最近在博客上发布了 Dapr 完成模糊测试审核[1]的文章,该审计是 CNCF 通过模糊测试改善[2]开源云原生项目安全状况的计划的一部分.该审计由 Ada Logics[3] 于 20 ...
- Sentieon实战:NGS肿瘤变异检测流程
肿瘤基因突变检测是NGS的一个重要应用,其分析难点主要在于低频变异的准确性.不同于遗传病检测,肿瘤样本类型多样,测序方法和参数复杂,且缺乏对应各种场景的公共标准真集.再加上常用开源软件经常遇到的准确性 ...
- 采集douban
# -*- coding: utf-8 -*-"""Created on Thu Oct 31 16:14:02 2019 @author: DELL"&quo ...
- CDMP国际数据治理认证训练营来了(7-8月)
大家好,我是独孤风,一位曾经的港口煤炭工人,目前在某国企任大数据负责人,公众号大数据流动主理人.在最近的两年的时间里,因为公司的需求,还有大数据的发展趋势所在,我开始学习数据治理的相关知识. 经过一段 ...
- MySQL数据库的集群方案
读写分离结构(主从) 读多写少,也就是对数据库读取数据的压力比较大. 其中一个是主库,负责写入数据,成为写库:其他都是从库,负责读取数据,成为读库. 对我们的要求: 读库和写库的数据一致: 写数据必须 ...