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,你希望数组整体的累加和尽可能大。 你有两个魔法卷轴,的更多相关文章

  1. VS2008 格式化时候乱码 或者 为全为0

    前几天一直发现写入文件的数据全是0 ,找了非常长时间发现问题在以下的地方: P:a是一个float数,如31.000000,然后运行以下的格式化语句时,结果str的值全是0. (我知道讲float格式 ...

  2. 使用OC语言编写两个超大数相乘或相加的算法的思路和超大正整数相乘的代码

    正文: 在编程中,无论是OC还是C亦或是C++语言,所声明的整数变量都会在内存中占有固定的存储空间,而这些存储空间都是固定的. 比如我们知道的int.long.short.unsigend int.u ...

  3. 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,求所有操作完毕后,所有节点的值 ...

  4. 偶然在博客中见对百度一个面试题的探讨,写些自己的看法以及指出探讨中不对的观点:百度面试题:求绝对值最小的数 有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现 例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。

    今天申请了博客园账号,在下班后阅览博客时发现了一个关于百度面试题探讨的博客(其实是个很基础的问题),此博客url为:http://www.blogjava.net/nokiaguy/archive/2 ...

  5. 使用Go语言编写区块链P2P网络(译)(转)

    转自:https://mp.weixin.qq.com/s/2daFH9Ej5fVlWmpsN5HZzw 外文链接: https://medium.com/coinmonks/code-a-simpl ...

  6. Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架

    转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏 ...

  7. 用 C 语言编写一个简单的垃圾回收器

    人们似乎觉得编写垃圾回收机制是非常难的,是一种仅仅有少数智者和Hans Boehm(et al)才干理解的高深魔法.我觉得编写垃圾回收最难的地方就是内存分配,这和阅读K&R所写的malloc例 ...

  8. linux c语言编写一个shell壳

    目的:我们要用c语言编写一个shell可以运行在linux机器上的. 介绍:shell所在的层次 我们要做的是操作系统,用于用户与操作系统进行交互的myhsell 思路:用户输入  一行字符串,我们先 ...

  9. 近50种语言编写的“Hello, World”,你会几种?可不要贪杯哦~

    本文转自公众号CSDN(ID:CSDNnews)作者:Sylvain Saurel,译者:风车云马

  10. 用Java语言编写一个简易画板

    讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目 ...

随机推荐

  1. 提高生产力的最佳免费开源终端:WindTerm

    哈喽,大家好!我是程序视点的小二哥! 前言 自从当上程序员以来使用频率最多的不是vscode,也不是github,而是终端!!! 小师妹使用过很多的终端工具,什么Tabby,Putty,Wrap等等, ...

  2. 包含引用类型字段的自定义结构体,能作为map的key吗

    1. 引言 在 Go 语言中,map是一种内置的数据类型,它提供了一种高效的方式来存储和检索数据.map是一种无序的键值对集合,其中每个键与一个值相关联.使用 map 数据结构可以快速地根据键找到对应 ...

  3. 【Python&GIS】矢量数据投影转换(WGS84转地方坐标系)

         又是掉头发的一天,今天的任务是将WGS84坐标系的点转成地方坐标系,并判断点是否在某个面内,找了半天的资料什么四参数.七参数啥的太复杂了.这里使用Python的ogr, osr库内置的坐标转 ...

  4. [ARM汇编]计算机原理与数制基础—1.1.3 二进制补码

    在计算机中,为了表示有符号整数(即正数和负数),通常采用二进制补码表示法.二进制补码不仅可以表示负数,还能简化计算机的加法和减法运算.接下来,我们将介绍二进制补码的概念及其计算方法. 原码.反码和补码 ...

  5. 如何在矩池云上安装和使用 Stata

    Stata是一款功能强大的统计分析软件,本文提供了如何在矩池云安装使用 Stata,以及如何在 Jupyter 中使用 Stata 的简要教程. 安装 Stata 时需要确保按照官方指南进行操作,St ...

  6. PySide6(Qt for Python) QTableWidget表头边框线问题

    这个问题是在Windows10平台下特有问题. 网络上有很多Qt C++的解决方案.但是没有特定的PySide6的解决方案(以下是Qt C++的解决方案). https://blog.csdn.net ...

  7. R语言中的跨平台支持:如何在Windows、MacOS和Linux上使用R语言进行数据分析和可视化

    目录 当今数据科学领域,R语言已经成为了数据分析和可视化的流行工具.R语言具有强大的功能和灵活性,使得它可以在各种不同的平台上运行,包括Windows.MacOS和Linux.因此,本文将介绍R语言中 ...

  8. 记一次Native memory leak排查过程

    1 问题现象 路由计算服务是路由系统的核心服务,负责运单路由计划的计算以及实操与计划的匹配.在运维过程中,发现在长期不重启的情况下,有TP99缓慢爬坡的现象.此外,在每周例行调度的试算过程中,能明显看 ...

  9. 每日一题 力扣 1377 https://leetcode.cn/problems/frog-position-after-t-seconds/

    力扣 1377 https://leetcode.cn/problems/frog-position-after-t-seconds/ 这道题目用dp去做,构建邻接矩阵,做的时候需要注意题目条件,如果 ...

  10. 如何修改电脑的BIOS密码?

      本文介绍设置.修改Windows电脑BIOS模式密码的具体方法.   一般的,电脑默认都是不含有BIOS密码的,可以直接在开机时不输入任何密码进入BIOS模式:而在某些特定的场合,我们可能需要对其 ...