2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子相关的知识,希望对你有一定的参考价值。
2022-05-25:最大子段和是
一个经典问题,即对于一个数组找出其和最大的子数组。
现在允许你在求解该问题之前翻转这个数組的连续一段,
如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子数组得到的是(1,2,5,4,3,6),
则翻转后该数组的最大子段和最大能达到多少?
来自字节,
几乎一样的题,来自字节笔试第4题。
给定两个数組values和numbers,
values[i]表示i号宝石的单品价值,
numbers[i]表示i号宝石的数量,
i号宝石的总价值 = values[i] * numbers[i]。
如果有一种魔法,可以翻转任何区间L…R的宝石,也就是改变L…R的宝石排列,变成逆序的。
求在允许用一次魔法的情况下,任取一段连续区间,能达到的最大价值。
这两个问法解法都几乎一样,区别无非是:
美团的: 可进行一次翻转情况下,子数组最大累加和;
字节的: 可进行一次翻转情况下,子数组最大价值和。
来自美团。
答案2022-05-25:
从左往右:dp[i]左=max(arr[i],dp[i-1]+arr[i])
从右往左:dp[i]右
逆序的这段,既不会贯穿,也不会在内部。也就说会选择逆序的一部分,只有这种可能。
左+部分逆序 等价于 右+部分逆序。
代码用rust编写。代码如下:
use rand::Rng;
fn main()
let len: i32 = 5;
let value: i32 = 20;
let test_time: i32 = 20000;
println!("测试开始");
for _i in 0..test_time
let n: i32 = rand::thread_rng().gen_range(0, len) + 1;
let mut arr = random_array(n, value);
let ans1 = max_sum_reverse1(&mut arr);
let ans2 = max_sum_reverse2(&mut arr);
if ans1 != ans2
println!("出错了!");
for num in &arr
print!(" ", num);
println!("");
println!("ans1 = ", ans1);
println!("ans2 = ", ans2);
break;
println!("测试结束");
fn max_sum_reverse1(arr: &mut Vec<i32>) -> i32
let mut ans: i32 = i32::min_value();
for l in 0..arr.len() as i32
for r in l..arr.len() as i32
reverse(arr, l, r);
ans = get_max(ans, max_sum(arr));
reverse(arr, l, r);
return ans;
fn reverse(arr: &mut Vec<i32>, mut l: i32, mut r: i32)
while l < r
let tmp = arr[l as usize];
arr[l as usize] = arr[r as usize];
l += 1;
arr[r as usize] = tmp;
r -= 1;
fn max_sum(arr: &mut Vec<i32>) -> i32
let mut pre = arr[0];
let mut max = arr[0];
for i in 1..arr.len() as i32
pre = get_max(arr[i as usize], arr[i as usize] + pre);
max = get_max(max, pre);
return max;
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T
if a > b
a
else
b
fn max_sum_reverse2(arr: &mut Vec<i32>) -> i32
let n = arr.len() as i32;
let mut prefix: Vec<i32> = vec![];
for _i in 0..n
prefix.push(0)
prefix[(n - 1) as usize] = arr[(n - 1) as usize];
let mut i: i32 = n - 2;
while i >= 0
prefix[i as usize] = arr[i as usize] + get_max(0, prefix[(i + 1) as usize]);
i -= 1;
let mut ans = prefix[0];
let mut suffix = arr[0];
let mut max_suffix = suffix;
for i in 1..n
ans = get_max(ans, max_suffix + prefix[i as usize]);
suffix = arr[i as usize] + get_max(0, suffix);
max_suffix = get_max(max_suffix, suffix);
ans = get_max(ans, max_suffix);
return ans;
// 为了测试
fn random_array(n: i32, v: i32) -> Vec<i32>
let mut arr: Vec<i32> = vec![];
for _i in 0..n
arr.push(rand::thread_rng().gen_range(0, v) - rand::thread_rng().gen_range(0, v));
return arr;
执行结果如下:
以上是关于2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子的主要内容,如果未能解决你的问题,请参考以下文章