求一个数组中两个不重叠子数组和的差的最大值

一个题目,据说来自Hired online test

#!/usr/bin/env python3
# coding: utf-8

"""
Challenge 5: Maximum Difference

Given an array of integer elements, a subsequence of this array is a set of
consecutive elements from the array (i.e., given the array
v: [7, 8, -3, 5, -1], a subsequence of v is 8, -3, 5)

Your task is to

   - write a function that finds a left and a right subsequence of the array
     that satisfy the following conditions
   - the two subsequences are unique (they don't have shared elements)
   - the difference between the sum of the elements in the right subsequence
     and the sum of the elements in the left subsequence is maximum
   - print the difference to the standard output (stdout)

Note that your function will receive the following arguments:

   - v, which is the array of integers

Data constraints

   - the array has at least 2 and at most 1,000,000 numbers
   - all the elements in the array are integer numbers in the following range:
     [-1000, 1000]

Efficiency constraints

   - your function is expected to print the result in less than 2 seconds

Example

   Input                               Output
   --------------------------------    ------
   v: 3, -5, 1, -2, 8, -2, 3, -2, 1    15

Explanation

   - The left sequence is: -5, 1, -2 and the right sequence is: 8, -2, 3.
"""


def maxdiff(v):
    # Write your code here
    # To print results to the standard output you can use print
    # Example print "Hello world!"
大意:给定一个数组,找到一个左边的子数组和一个右边的子数组,这两个子数组不重叠,且右边的子数组和减去左边的子数组和这个差值最大

思路:

如果对于每个下标i,我们能得到,arr[0,i]的最小子数组和minFromLeftTo[i],arr[i+1,n)的最大子数组和maxFromRightTo[i+1],则结果就是max{maxFromRightTo[i+1] - minFromLeftTo[i],arr[i+1,n), 0 <=i <= n-2}。

minFromLeftTo[i]和maxFromRightTo[i]均可以遍历一次数组在O(n)时间内得到,因此时间复杂度为O(n),另外,我们需要O(n)的空间来保存辅助数组,因此空间复杂度也为O(n)。

#include <cstdio>
#include <algorithm>
using namespace std;

const int MAX = 1000000;
int leftTo[MAX];

int maxDiff(int arr[], int n)
{
	if(n < 2) return 0;
	if(n == 2) return arr[1] - arr[0];

	leftTo[0] = arr[0];
	int i = 1, sum = arr[0] > 0 ? 0 : arr[0];
//find out minimum sequence sum from 0 to i includingly
	for(; i < n; ++i){
		leftTo[i] = min(leftTo[i-1], arr[i]);
		sum += arr[i];
		if(sum > 0) sum = 0;
		else leftTo[i] = min(leftTo[i], sum);
	}
//find out maximum sequence sum from n-1 to i includingly
	int res = arr[n-1] - leftTo[n-2], maxSum = arr[n-1];
	sum = arr[n-1] < 0 ? 0 : arr[n-1];
	for(i = n-2; i > 0; --i){
		maxSum = max(maxSum, arr[i]);
		sum += arr[i];
		if(sum < 0) sum = 0;
		else maxSum = max(maxSum, sum);
		res = max(res, maxSum - leftTo[i-1]);
	}
	return res;
}

int main()
{
	int arr[] = {3, -5, 1, -2, 8, -2, 3, -2, 1};
	printf("%d\n", maxDiff(arr, sizeof(arr)/sizeof(arr[0])));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值