一个题目,据说来自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;
}